NASM手册阅读笔记(2) - 基础内容
EQU
var equ 1
与MASM中一致,定义常数
TIMES
与MASM 的 REPT 或者DUP 指令功能类似
其更像是 rept 的地条指令版本
TIMES n xxxx => REPT n
xxxx
ENDM
比如:
功能:初始化buffer的内容,并把长度凑满 64字节
BUFFER: DB 'HELLO,WORLD'
TIMES 64-($-BUFFER) DB ' '
注意times 指令不能用在宏上
$ 与$$
$ 表示本行相对于整个程序的偏移地址
$$ 变本缩在段的地址,所以 $- $$ 就是段内的地址
本地LABEL
以点 . 开始的LABEL会被认为是上一个非点 . 开始的的子label
比如
LABEL1 XXXX
XXXX
.CHILD XXXX ; 实际上他是LABEL1.CHILD
XXXX
.CHILD2 XXXX ; 实际上他是LABEL1.CHILD2
JMP .CHILD ; 本同一个LABEL1的作用于内可以省略父LABEL1,实际是 LABEL1.CHILD
LABEL2 XXXX
XXXX
.CHILD XXXX ; 实际上他是LABEL2.CHILD
JMP .CHILD ; 本同一个LABEL2的作用于内可以省略父LABEL2,实际是 LABEL2.CHILD1
JMP LABEL1.CHILD ; 由于不在一个作用域内,所以要指定全名称
FAR CALL
格式
CALL 段地址:偏移地址
这两地址必须是立即数,所以你在编译的时候就必须知道实际地址,不能通过给内存赋值来调用,不过倒是可以在运行的过程中动态修改指令完成类似功能,这就是有点类似windows或者Linux的加载器干的活了。
INCBIN
INCBIN “文件”
包含二进制数据,这会在INCBIN所在位置直接将指定文件的二进制数据包含进来
强制类型转换 BYTE WORD DWORD NOSPLIT
在使用内存地址的可以强制指定格式, 格式如下
mov ax, [word bx]
mov ax,[byte bx]
NOSPLIT 的作用是分割指令,比如
[ax*2+offset] 实际被转换为[ax+ax+offset]
使用 [nosplit ax*2 + offset] 会强制按照字面意思编译,这样应该是能加快指令执行速度?
STRICT 取消强制类型转换的优化
比如
PUSH DWORD 33
由于 33 用 BYTE 就能存储,所以编译器会直接优化成
PUSH BYTE 33
但是这是我们不希望看到的,会到底后面的定位出错
所以这个时候就可以使用
PUSH STRICT DWORD 33
这样编译器就不会给我们优化掉
算数运算符
+ - * / % %% | ~ & << >>
加减乘除 取余 与或非 左移 右移 都支持 和C的用法一样
SEG/WRT
主要是用在16位汇编的时候取 段地址的
比如
MOV AX, SEG LABLE1 ; LABLE1的段地址
MOV AX, LABLE1 ; LABLE1 的偏移地址
WRT 的话是可以实用偏移地址的计算根据指定的地址来计算
比如
MOV AX, LABLE WRT 我指定的段地址
这样传到AX的LABLE的偏移地址是根据 我指定的段地址计算而来的
这两个指令已经毫无用武之地的,因为这两个指令有两个条件
1. 16位汇编
2. 编译成windows obj格式
现在window哪有16位的,32位都快淘汰了,唯一要用到16位的就是MBR,大还是MBR编译格式是BIN啊,所以这两伪指令完全用不上的