汇编语言(王爽第三版)检测点16
检测点16.1
下面的程序将code段中a处的8个数据累加,结果存储到b处的双字中,补全程序。
assume cs:code
code segment
a dw 1, 2, 3, 4, 5, 6, 7, 8
b dd 0
start: mov si, 0
mov cx, 8
s: mov ax, a[si]
add word ptr b[0], ax
adc word ptr b[2], 0
add si, 2
loop s
mov ax, 4c00H
int 21H
code ends
end start
程序分析:
【1】a代表了code段的首地址code:00,由于dw,也代表了a开始的这一小段内存都是按照字单元存储的。从code:[0]~code:[15],也就是,a[0]~a[15];a[si]代表了从code:00开始的偏移量为si的内存单元。此内存单元是字单元,故si的偏移量是2个字节。
【2】b代表了code段中紧邻a段地址的code:[16](首地址),一个双字的单元,它存储位置是code:[16]~code:[19],也就是b[0]~b[3];剩下的空间都是真正的CPU执行的代码了。
【3】mov ax, a[si]代码含义:将偏移量为si的段地址(或内存段首地址)为a的内存单元按字单元送入到ax中。
【4】add word ptr b[0], ax,代码含义:将ax值与b标号的低16位做加法,结果存储在b标号的低16位中;此时b代表的是双字单元,如果add b, ax;编译器肯定报错,因为它们的类型不匹配。此处必须指定b[0]是按照字单元作为存储结构的。
【5】adc word ptr b[2], 0;代码含义:带进位加法,将0与上一指令中的CF值相加,结果存储在b的高16位单元中。目的:防止低16位值产生进位。同理:此处必须指定b[2]是按照字单元作为存储结构的。这个实例就是高位不溢出加法的套路。对于无符号数加法它的最大允许范围是(0000 0000H~FFFF FFFFH):0~4294967295
【6】add si, 2;代码含义:si的偏移量,由于a的偏移量是按照字单元偏移,故si为2个字节的偏移量。
检测点16.2
下面的程序将code段中a处的8个数据累加,结果存储到b处的双字中,补全程序。
assume cs:code, ds:data
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
data ends
code segment
start: mov ax,data
mov ds,ax
mov si,0
mov cx, 8
s: mov al, a[si] ;a[si]代表的是一个字节。
mov ah, 0 ;ah置零,防止高位不为零
add b, ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start
程序分析:
【1】即使在assume这个伪指令中将ds和data联系在一起(C语言的全局声明意思)。如果没有将data的段地址赋值给ds,那么[si]寻址的内存单元是错误的,并不是ds:[si]或a[si]。
【2】如果在assume中没有ds:data,那么在code段中使用a和b是不可能的。因为a和b在code段是不可以见的。
【3】a[si]代表的是一个字节(它已经代表地址和单元长度了),赋值给ax是错误的,应该赋值给al,别犯这样的低级错误。(ah)=0,是防止高位不为零,al+ah组合成数据就是(ax)。