1. 通过seg和offset操作符获取标号的段地址和偏移地址:
1) 这两个都是伪指令,都是属于编译器的操作符,不能直接翻译成机器代码,前者是segment的缩写,而后者的意思就是“偏移量”;
2) 这两者可以作用于任何标号,前者用于获取标号所在段的段基,后者用于获取标号所在段的偏移地址,这里的段都是由"XXX segment"定义的段,而这个XXX(也是标号)就是段基了;
3) offset还可以作用于变量,而seg只能作用域标号,不能作用于其它东西(否则会报错的);
变量,是编译器的一种特殊功能,可以在某个地方用"VarName = Value"的形式定义一个以VarName作为代码中的代号的数据空间,可以直接在代码中把它当一个内存单元来使用,比如”mov ax, VarName“,而传送的值就是VarName所代表的那个内存中的数据Value,而offset VarName就相当于C语言的&(取地址运算符),可以获得该变量所在段的偏移地址;
!注意:offset只用于标号和变量,而seg只用于标号,不要用它们作用域其它任何东西,有时候不会报错,但是在程序中可能会出现无法预测的错误;
4) 示例:
assume cs:code, ds:data, ss:stck
data segment
db 3 dup(0)
s1: mov ax, bx
data ends
stck segment
db 5 dup(0)
s2: nop
mov ax, bx
stck ends
code segment
start:
mov ax, seg data
mov ds, ax
mov ax, seg stck
mov ss, ax
mov ax, offset s1
mov bx, offset s2
mov cx, seg s1
mov dx, seg s2
mov ax, 4C00H
int 21H
code ends
end start
运行结果:
可以看到s1和s2的offset都是相对各自段的段基的偏移量(s1的段基是data,偏移量是3,s2的段基是stck,偏移量是5),而ds和cx相等(都是data)、ss和dx相等(都是stck),虽然以前的那种写法"mov ax, code"也行,但不过这种更正式,建议以后都是用"mov ax, seg code",这样更符合逻辑;
!以后要常用seg和offset!养成良好的习惯!
5) 不要把标号当做立即数使用!
i. 上面已经提到过了,在有些情况下是可以将标号当做立即数使用,比如上面讲过的"mov ax, codesg"等,但是这是有前提的;