[原]nasm语法

工具:
nasm 汇编
gcc  编译c
ld    进行链接
kscope 查看源代码
make 工程管理
khexedit  分析二进制文件

一:
nasm源文件布局:
像其他汇编器一样, nasm源文件包含四个域的组合。(除了宏, 或者预编译器指示, 或者汇编指示 )
label标号: 指令 操作数 ;注释
通常, 这些域是可选的。 当然, 操作数域是根据指令的要求来放置,或者去掉的。

nasm使用/作为行链接符, 如果一行以/结尾, 下一行认为是本行的继续.

nasm对于空格没有限制; 标号可以在前面包含空格, 或者指令前可以没有空格. 标号后的冒号是可选的. (可以使用-w+orphan-label选项来提示某行只有标号).

标号中的字符包括字母, 数字, _$#@~.?  可以字母开头,  . (.有特殊的含义!), _和? 也可以作为头部. 一个标识符可能也有$前缀, 表明是作为标识符读取的, 并不是保留字; 因此, 如果你链接的其他模块定义了符号eax, 你可以通过$eax去区分符号和寄存器. 标识符最大的长度为4095.

指令域可能包含任何机器指令: 奔腾指令, 奔6指令, FPU指令, MMX指令, 甚至未文档化的指令,都可以被支持. 指令可能包含前缀LOCK, REP, REPE, REPZ, 或者REPNZ, REPNE. 显式的地址大小和操作数大小前缀A16, A32, A64, O16 和O32, O64 也被提供了. 一个使用他们的例子在10章.
你可以使用段寄存器名字作为指令前缀: 编码 es mov [bx], ax 等价于 mov [es:bx], ax.  但是对于LODSB等类似指令, 没有操作数, 但是也需要一个段寄存器, 除了es lodsb 没有其他办法.

一个指令一下情况需要前缀: 前缀是cs, a32, lock, repe可以独立出现在一行, nasm会生成带前缀的代码.

另外, 对于实际的机器指令, nasm支持伪指令.

指令操作数有很多形式: 寄存器, 有效地址, 常数, 或者表达式.

对于x87浮点指令, nasm接受叫大范围的语法, 使用双操作数, 或者使用nasm本地单操作数.例如
fadd st1
fadd st0, st1
fadd st1, st0
fadd to st1
几乎所有x87引用内存的浮点指令都使用前缀DWORD, QWORD, TWORD, 表明内存操作数的大小.

2伪指令:
 DB DW DD DQ DT DY; 他们的未初始化对应物是RESB RESW RESD RESQ REST RESO和 RESY, INCBIN命令, EQU命令, TIMES前缀.

2.1DB声明初始化数据
db  0x55   db 0x55, 0x56, 0x57
db 'a', 0x55
db 'hello', 13, 10, '$'
dw 0x1234
dw 'a'   ;数字
dw 'abc' ;对其二字节 
dd 0x12345678
dd 1.234567e20
dq 0x1234567abc
dq 1.23456e20
dt  1.2345e20
DT, DO, DY 不接受数字常量作为操作数
2.2RESB  声明为初始化数据
RESB RESW RESQ RESD REST RESO RESY 用来声明模块的BSS区域: 声明为初始化的存储区域(block start by symbol). 每个产生一个操作, 字节数, 字数, 双字数, 或者其他要保留的大小. RESB类型伪指令是一个重要的表达式.
例如:
buffer:  resb 64
wordvar: resw 1
realarray: resq 10
ymmval: resy  1 在ymm寄存器中

2.3INCBIN包含外部二进制文件:
INCBIN从早期的DevPac汇编器中借来的: 包含一个二进制文件verbatim到输出文件中去. 这可以便于包含图形文件, 声音文件直接到一个游戏执行文件中去. 可以有一下3种调用方式:
incbin "file.dat"   整个文件
incbin "file.dat", 1024  忽略头1024字节
incbin "file.dat", 1024, 512 忽略头1024字节, 最多包含512字节
INCBIN即是指示, 也是宏.

2.4EQU:定义常数
EQU定义一个符号赋值常数: 当使用EQU, 源代码必须包含标号.
message  db  'hello'
mslen   equ   $-message

2.5TIMES: 重复指令或者数据
TIMES前缀引起指令汇编多次. 等价于DUP
zerobuf:   times  64  db 0
或者类似; 但是TIMES功能更多. times的参数不仅仅是数字常量, 也可以是表达式
buffer: db  'hello'
times  64  -$+buffer  db ' '
将会保存足够的空间, 使buffer达到64. 最后, times可以应用到一般指令, 你可以编码平凡非回转循环在其中:
times  100  movsb
注意到: times 100 resb  1 和 resb 100没有区别, 除了后者可以更快的汇编.
times的操作数是重要的表达式.
注意到times不能应用到宏中: 原因是times在宏阶段后处理, 允许times使用参数包含表达式, 例如64-$+buffer.
为了重复多余一行的代码, 或者复杂宏, 使用预编译指令%rep

3有效地址:
一个有效地址是任何操作数, 在指令中引用内存. 有效地址, 在nasm中有很简单的语法: 由表达式组成, 等价于期望的地址, 被方括号包围:
wordvar  dw 123
mov   ax , [wordvar]
mov   ax, [word+1]
mov   ax, [es:wordvar +bx]
任何不符合这个规则的东西都不是有效的内存引用.例如: es:wordvar[bx]
更复杂的有效地址, 例如包含多个寄存器:
mov  eax , [ebx*2 + ecx + offset]
mov ax, [bp + di + 8]
nasm有能力对这些有效地址作代数运算, 因此这些看起来不合法的表达式, 是正确的:
mov  eax, [ebx*5] ;汇编为 ebx*4 + ebx
mov  eax, [label1*2-label2] ;汇编为: label1 + (label1 - label2)
一些形式是有效地址, 含有超过一种汇编形式; 大多数情况下, nasm会生成最小的形式. 例如对于[eax*2 + 0]和[eax + eax], 有两种不同的汇编形式, nasm会生成后者.

nasm有一个提示机制, 可以使[eax+ebx] 和[ebx+eax]生成不同的代码; 这个偶尔有用, 因为[esi+ebp]和[ebp+esi]有不同的默认段寄存器.

然而, 你可以强制nasm生成有效地址以特殊形式, 通过使用关键字BYTE, WORD, DWORD, NOSPLIT. 如果你使用[eax+3]汇编成双字偏移, 而不是单字节, 你可以使用[dword eax+3].
类似的, 你可以强制nasm使用单字节偏移对一个小的数值, 没有在第一遍中发现.,[byte eax+offset].
作为特例, [byte eax]编码[eax+0], 使用一个字节偏移0, [dword eax]编码双字偏移. 正常形式[eax]没有偏移域.

以上描述的在你从16位代码中访问32位段中的数据时也是有用的. 可以查看10.2混合大小寻址章.
特别地, 如果访问已知偏移的数据比当前16位值大, 如果你不指明这是个dword偏移, nasm将会使偏移的高字节丢失.

类似的, nasm会分割[eax*2]为[eax+eax]因为允许偏移部分被省略, 空间节省; 事实上, 他也会分割[eax*2 + offset]为[eax+eax +offset]. 你可以通过使用NOSPLIT来抵抗这种行为: [nosplit eax*2]强制按字面生成[eax*2 + 0].

64位模式下, nasm会默认生成绝对地址. rel关键字使之生成rip相关地址.

3.5常数:
nasm理解四种形式的常数:数字, 字符, 字符串, 浮点数.
4.1数字常数:
nasm允许你指定数字以各种进制: 你可以添加后缀H, X, Q, O, B用于16进制, 8进制, 2进制, 你也可以使用0x, 或者前缀$.
当前nasm使用0h 0o 0q 0b只是16, 8 ,2进制.
例如:
mov  ax  , 200
mov  ax, 0200
mov  ax, 0200d
mov ax, 0d200
mov ax, 0c8h
mov ax, $0c8
mov ax 310o
mov ax, 11001000b

4.2字符串:
字符串由"", '', ``包含. 单引号, 双引号等价的, 反引号用于特殊字符.
db  `/u263a`
db `/xe2/x98/xba`
db 0e2h, 098h, 0bah

4.3字符常量
mov  eax, 'abcd'

4.4字符串常量
db  'hello'

4.6浮点数
db  -0.2
dw -0.5
dd  1.2
dd 1.222222222
dd 0x1p+2
dq 1.e10

5表达式:
nasm表达式类似于c. 表达式等价于64为整数, 将会在后来被调整到合适大小.
nasm支持两种表达式词法记号, 允许在当前汇编位置计算: $和$$词法记号. $计算汇编位置, 在包含行的开始; 所以你可以编码无限循环 JMP $. $$计算当前段开始; 所以你可以通过$-$$得知在当前段中的位置.

nasm提供算术操作:
|位或, ^异或 &位与 << >>位移 + - 加减, * / // % %% 乘法和除法
/无符号乘法, //有符号除法, %无符号, %%有符号求模操作.

nasm不提供对于有符号的求模操作符的强力操作的保证.

因为%字符被宏预编译扩展使用, 你应该保证被空格后接有符号, 无符号求模操作符.
单操作符: + - ~ ! SEG
~求补, !求反, SEG求操作数段地址.

6SEG WRT
当写16位大程序, 必须被分割为多个小段, 因此很有必要去定位段的地址的一部分, 通过一个符号. NASM支持seg操作符, 来完成这个功能.

seg操作符返回符号所在的段的基址, 定义段基地址相对于符号的偏移是有意义的. 因此代码:
mov  ax, seg symbol
mov  es, ax
mov bx, symbol
将会加载ES:BX指向符号的有效指针.

事情可能会比这个复杂: 因为16位段和组可能会重叠, 你可能偶尔希望通过不同的段基地址来引用一些符号. nasm允许这样作, 通过使用wrt关键字, 你可以这样做:
mov  ax, werid_seg
mov  es, ax
mov  bx, symbol wrt werid_seg
去用不同的, 但是功能等价的指针指向符号symbol 加载到es:bx.(with reference to)

nasm支持段内的远调用, 和远跳转, 通过call segment:offset, segment, 和offset均代表立即数值. 因此要远调用一个过程, 你可能编码如下:
call    (seg  procedure): procedure
call    weird_seg : (procedure wrt weird_seg)
加入括号是为了清楚, 展示以上指令语法分析的目的.

nasm支持语法call far procedure 作为上面第一种的同义词. jmp在以上例子中功效等同于call:

为了声明一个对数据的远指针在数据段中, 你应该这样:
dw   symbol,  seg  symbol
nasm没有类似的同义语, 虽然你可以使用宏来发明一个.

7抑制优化 STRICT
当在2或以上优化选项下, 汇编代码, nasm会使用大小限定符, 但是会给他们最小的大小. 关键字strict可以用于抑制这种优化.
例如: 在16位模式下:
push dword 33
被编码为66 6a 21, 而  push dword 33编码为 66 68 21 00 00 00

8关键表达式:
尽管nasm有可选的多边优化, 有若干表达式必须在第一遍中被解析, 这些称为关键表达式.

第一遍用于决定所有汇编代码的大小, 在第二遍, 当生成所有的代码时, 知道所有的代码引用的符号地址. 因此, nasm不能处理的事是代码大小决定于后面声明的符号的值, 在代码被提问时. 例如:
times (label-$) db 0
label: db  'where am i'
这种情况下times的参数合法的等价于任何值; nasm将会拒绝这种情况, 因为他不能在首次见到时知道times行的大小.
times (label-$+1) db 0
label: db "now where am i"
这种情况下, 任何值都错.

nasm拒绝这些例子, 通过一个叫做关键表达式的概念, 被定以为一个表达式, 其值需要在第一遍中计算出来, 因此只能依赖于前面定义的符号. times的参数是关键表达式.

本地变量:
对于以.开始的符号, nasm给予特殊的对待. 一个标号以一个原点开始, 被认为是局部变量, 意味着和以前的非局域变量存在联系, 例如:
label
.loop
jne  .loop
ret
label2
.loop
jne .loop
ret
在上面的代码片段中, 每个jne指令跳转到前面的行, 因为两个.loop的定义是隔离的通过前面的非局部变量的联系的效力.

这种局部标号的处理借鉴于amiga汇编器; 然而, nasm更进了一步, 允许访问局部变量从代码的另一个部分. 这通过定义局部变量根据前面的非局部变量: 第一个.loop的定义实际是定以为label1.loop, 第二个是label2.loop, 因此, 你如果真的需要
label3
jmp label1.loop
有时是有用的, 在宏里, 例如, 可以定义一个标号可以从任何地方引用, 但是不会干预正常的局部标号机制. 这种标号不能是非局部的, 因为定义他的宏不知道label的全名. nasm因此引入了第三类标号, 可能值在宏中使用: 如果以..@开始的一个标号, 不会对局部标号产生作用:
label
.local:
..@foo:
label2:
.local:
jmp ..@foo
nasm有能力去定义其他特殊符号, 以..开始例如
..start, 用来指定obj文件的入口.









 


 












作者:liyonghelpme 发表于2010/6/11 18:19:00 原文链接
阅读:2221 评论:0 查看评论

转载于:https://www.cnblogs.com/liyonghelpme/archive/2010/06/11/4273548.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/410994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#仿QQ皮肤-常用用户控件EnterFrom1和窗体EntryForm的实现

导读部分 ------------------------------------------------------------------------------------------------------------- C#仿QQ皮肤&#xff0d;实现原理系列文章导航 最新版源码下载 http://www.cckan.net/thread-2-1-1.html 本次是我们窗体实现的最后一节&#xff0c…

助教小结13

本周总结&#xff1a; 主要为完成团队任务五的批改 整体完成的还可以 第1组、第9组&#xff1a;未点击提交按钮总成绩打八折 优秀作业&#xff1a; 第5组&#xff1a;https://www.cnblogs.com/lishuya/p/11088462.html 千帆竟发图&#xff1a; 转载于:https://www.cnblogs.com/…

java工作台无法显示_【Eclipse】使用指南(18)搜索工作台

Searching the workbench搜索工作台In this section, you will search the workbench for Java elements.本小节&#xff0c;你将在工作台中搜索Java元素。In the Search dialog, you can perform file, text or Java searches. Java searches operate on the structure of the…

Gridview 鼠标悬浮光棒效果

代码 1 protectedvoidGridView1_RowDataBound(objectsender, GridViewRowEventArgs e)2 {3 4 //如果是绑定数据行 5 6 if(e.Row.RowType DataControlRowType.DataRow)7 {8 9 //鼠标经过时&#xff0c;行背景色变 10 e.Row.Attributes.Add("onmouseover",11 "cu…

神策埋点

首先进入后台管理点击生成导入代码&#xff1a; 选好选项后点生成&#xff1a; 以下是生成的代码&#xff1a; (function(para) {var p para.sdk_url, n para.name, w window, d document, s script,x null,y null;if(typeof(w[sensorsDataAnalytic201505]) ! undefined…

java 抽象类语法_JAVA基础语法8--多态/抽象类/抽象方法

多态继承、封装、多态、抽象是面向对象编程的四大基本特征。封装隐藏了类的内部实现机制&#xff0c;从而可以在不影响使用者的前提条件下&#xff0c;改变类的内部结构&#xff0c;同时保护了数据。继承是为了重用父类代码&#xff0c;同时为多态做准备。那么&#xff0c;什么…

(搬家文) c++引用深入探讨

(偶然翻起自己的旧博,忽然发现大三的时候写的这篇文章,仔细看看觉得写的还是那么回事,所以赶紧搭救出来) 引用的声明: 基本格式&#xff1a;引用类型 &引用名被引用对象 &运算符&#xff1a;声明运算符& 跟取地址运算符&和位异或运算符&没有任何关系ext…

参数作用域实践

auto参数&#xff0c;申明时可以忽略auto void fun(){int p 1;cout<<"p:"<<p<<endl;for(int i0;i<5;i){int p 10;cout<<"p:"<<p<<endl;}// 此处输出的还是外围作用域定义的p值1cout<<"p:"<<…

phpstudy2018修改php版本,phpstudy的php版本自由修改的方法

作为PHP开发的常用工具&#xff0c;phpstudy具有许多强大的功能&#xff0c;它可以连接到MySQL并检查服务器状态&#xff0c;感兴趣的话就随爱站技术频道小编一起来了解phpstudy的php版本自由修改的方法吧&#xff01;网上有着许多的网站集成搭建软件&#xff0c;比较出名的就有…

API网关从入门到放弃

前言 假设你正在开发一个电商网站&#xff0c;那么这里会涉及到很多后端的微服务&#xff0c;比如会员、商品、推荐服务等等。 那么这里就会遇到一个问题&#xff0c;APP/Browser怎么去访问这些后端的服务? 如果业务比较简单的话&#xff0c;可以给每个业务都分配一个独立的域…

BarTender操作遇到OLE DB遇到了错误0x80004005”的问题

在使用BarTender打印条码时操作遇到"OLE DB遇到了错误0x80004005”的问题 在打印时关掉数据库所连接的Excel文件即可转载于:https://www.cnblogs.com/edrp/archive/2010/07/18/1780122.html

震惊!垃圾分类居然能用Python搞定!

目录 0 引言 1 环境 2 需求分析 3 代码实现 4 后记 0 引言 纸巾再湿也是干垃圾&#xff1f;瓜子皮再干也是湿垃圾&#xff1f;&#xff1f;最近大家都被垃圾分类折磨的不行&#xff0c;傻傻的你是否拎得清&#xff1f;???自2019.07.01开始&#xff0c;上海已率先实施垃圾分类…

免费试用 Mobile Me

曾经尝试着注册过Mobile me&#xff0c;发现居然试用也要提供信用卡&#xff0c;而且地区选项里根本就没有中国&#xff0c;故愤然弃之。 今天忽然想再尝试一把&#xff0c;毕竟把mac、iphone&#xff0c;和即将到来的ipad连在一起是挺有意思的事情。 打开http://www.apple.com…

Postman: Test

Tests 参考&#xff1a;Writing Tests Testing examples 这里写测试用例&#xff0c;进行一些判断等等。即处理断言 下面新建了两个测试用例&#xff0c;名字分别是”Status code is 200“ 、”Status code name has string“。 “responseCode.code 200” 返回 True 或者 Fal…

比IETEST更好用的浏览器兼容性测试软件[绿色]

Xenocode Browser Sandbox 改变了基于 Windows 的浏览器兼容测试工具的游戏规则&#xff0c;只需点一下鼠标&#xff0c;就会直接打开一堆各式各样的浏览器窗口&#xff0c;你可以在不同版本的 IE, Firefox, Google Chrome, Safari 进行测试。是真正的测试&#xff0c;不是屏幕…

【期外】 (一)关于LSH :局部敏感哈希算法

LSH是我同学的名字&#xff0c;平时我会亲切的称呼他为离骚&#xff0c;老师好&#xff0c;左移&#xff08;leftshift&#xff09;&#xff0c;小骚骚之类的&#xff0c;最近他又多了一个新的外号&#xff1a;局部敏感哈希&#xff08;Locally sensitive hashing)。 好了&…

mysql n 存储结构,MySQL体系结构和存储引擎概述

一、定义数据库和实例数据库&#xff1a;物理操作系统文件或其他形式文件类型的集合。数据库文件可以是frm、MYD、ibd 结尾的文件。从概念上来说&#xff0c;数据库是文件的集合&#xff0c;是依照某种数据模型组织起来并存放于二级存储器的数据集合&#xff1b;实例&#xff1…