1. 偏移地址的表示方式汇总:
1) 偏移地址表示规则:在中括号[ ]中最多有一个基址寄存器、最多有一个索引寄存器、最多有一个立即数,这三者的顺序可以任意,之间必须用+相连,不得用其它符号;
2) 基址寄存器:是指bx(base register基址寄存器)和bp(base pointer基址指针),两者都属于基址寄存器,只不过bx作为偏移地址时默认ds为段基,而bp作为偏移地址时默认ss作为段基;
3) 索引寄存器:是指si和di(Source/Destination Index Register),但它们也称为串操作变址寄存器;
串操作是指在两个数组之间进行数据传递,一个作为源数组(偏移地址用si表示)另一个作为目的数组(偏移地址用di表示),由于使用这两个寄存器作为偏移地址时CPU有特殊的指令实现串操作而使速率非常快,因此数组之间数据传递尽量使用这两个寄存器而不要使用其它寄存器作为偏移地址,这也是传操作变址寄存器名字的由来;
!注意:当偏移地址中不包含基址寄存器时一律将ds作为默认段基;
4) 立即数前缀表示法:比如10[bx]就等于[bx + 10],es:2FH[si + bx]就等于es:[bx + si + 2FH];
5) 多维数组表示法:可以将三个部分分别用三个中括号[ ]括起来,比如[10H][bp][si],三者顺序可以任意,[si][10H][bx]也行!
!注意:偏移地址中的立即数是对后缀敏感的,同样需要用后缀识别它是几进制的,进制问题在汇编代码中是全局的!
5) 举例:
ds默认前缀: [si] [di] [si + 3] [si][9] [8][di] [0FH + di] [bx + di] [di][3][bp] [bx][si][30H] [di + bx + 3] [3 + si + bx] 3H[si + bx] == [si + bx + 3H] [5] ss默认前缀: [bp] [bp + si + 3] [bp][3H][di] 7[si + bp]
**可以看见[ ]内顺序可以任意,如果使用段前缀表示法,比如ds:[bp + si + 9]则能精确确定是哪个段的内存单元了!
6) 一个使用bp、si、di的示例:
将第一行welcome to masm!挪到第二行的内存空间中
assume cs:codesg codesg segment db 'welcome to masm!' db 16 dup('9') start: mov ax, codesg mov ds, ax mov ss, ax mov bx, 0 mov si, 0 mov bp, 0 mov di, 16 mov cx, 16 lp: mov al, [bx][si] mov [bp][di], al inc si inc di loop lp mov ax, 4C00H int 21H codesg ends end start运行结果:
2. 示例:将每行的第一个字母变为大写(每行刚好16个字符):
assume cs:codesg, ss:datasg datasg segment db '1. file ' db '2. edit ' db '3. search ' db '4. view ' db '5. options ' db '6. help ' datasg ends codesg segment start: mov ax, datasg mov ss, ax mov al, 11011111B mov bp, 3 mov cx, 6 lp: and [bp], al add bp, 16 loop lp mov ax, 4C00H int 21H codesg ends end start
3. 内存单元和立即数作用或者内存单元作为唯一的操作数的情况:
1) 在这种情况下就需要显式指明内存单元的类型了,可以使用byte ptr或word ptr操作符来指明内存单元是字节型的还是字型的;
!注意:这两个操作符是编译器提供的操作符,并不是汇编指令,不能直接一步翻译成二进制码;
2) 使用的情形:
i. 第一个操作数是内存单元而第二个操作数是立即数;
ii. 指令是单操作数,且该操作数是内存单元;
!!!!注意:如果内存单元和寄存器相互作用虽然显示指明内存单元类型不会编译报错,但是千万不要这样多此一举,有时会发生未知错误!
3) 示例:
mov byte ptr 10H[bx], 9 and word ptr [bp][di][0FCH], 1AH inc byte ptr [bx]
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">!注意:还是不能将[立即数]作为第一个操作数,编译器会将其理解成一个立即数看待的!</span>