【汇编随笔】王爽《汇编语言(第3版)》相关习题
P25 检测点2.2
(1)
偏移地址的取值范围在 0H ~ FFFFH 之间。
仅通过变化偏移地址寻址,根据物理地址计算公式:段地址 * 10H + 偏移地址。
已知段地址固定 0001H,即最小物理地址为 00010H,最大地址为 1000FH。
(2)
设偏移地址为 x,即公式为:SA * 10H + x = 20000H。
偏移地址的取值范围在 0H ~ FFFFH 之间。
最大值
当最大段地址时,偏移地址x为0。
代入公式:SA*10H + 0 = 20000H,简化后 SA = 20000H / 10H,SA = 2000H。
SA 最大为 2000H。
最小值
当最小段地址时,就要用最大偏移地址来代入。
代入公式:SA*10H + FFFFH = 20000H,简化后 SA = (20000H - FFFFH) / 10H。
求出值是 1000H,但这个结果是错的。
原因
假设段地址是1000H,那么久违反了段地址要为10H的倍数这条准则。
这就需要调整偏移地址的值,因为FFFFH是最大了,只能往下调整。
- 20000H - FFFFH = 10001H,十进制是 65537,除以 10H 有小数所以不是倍数。
- 20000H - FFFEH = 10002H,十进制是 65538,除以 10H 有小数所以不是倍数。
- 20000H - FFFDH = 10003H,十进制是 65539,除以 10H 有小数所以不是倍数。
- ...
- 20000H - FFF0H = 10010H,十进制是 65552,除以 10H 整除。所以这个偏移地址FFF0H才是最大的偏移地址。
求得实际最大偏移地址 FFF0H,代入上述公式中(SA = (20000H - FFF0H) / 10),求得值为 1001H。
SA 最小为 1001H。
反过来思考
当段地址定为多少,CPU无论怎么变化偏移地址都无法寻到 20000H。
小于 1001H,或大于2000H都无法寻到20000H单元。即此题段地址最小不能小于1001H,最大不能超过2000H。
P120 程序5.8
这里的0:200 ~ 0:20b能转换成0020:0~0020:b,因为它们指向的物理地址是相同的。
(实际情况下要根据不同的机器来写,比x86只有4根线表示段号)
第一轮asm,思路:复制ffff内存的东西先到dx中,修改ds,将dx东西复制到0020中。
assume cs:code
code segment
mov bx, 0
mov cx, 0bh
loopCode:
mov ax, 0ffffh
mov ds, ax
mov dl, ds:[bx]
mov ax, 0020h
mov ds, ax
mov ds:[bx], dl
inc bx
loop loopCode
mov ax, 4c00h
int 21h
code ends
end
但是这里有一个弊端,那就是ds在每个循环过程中被修改了两次。原始单位FFFF和目的单位0020相距大于64KB(偏移地址FFFFH),在不同的64KB段里,要设置两次ds,效率不高。
优化思路是:用两个段地址寄存器分别存放2个段地址,省略循环中要重复做12次的ds赋值。
第2轮优化
assume cs:code
code segment
mov bx, 0
mov cx, 0bh
mov ax, 0ffffh
mov ds, ax
mov ax, 0200h
mov es, ax
loopCode:
mov dl, ds:[bx]
mov es:[bx], dl
inc bx
loop loopCode
mov ax, 4c00h
int 21h
code ends
end
P121 实验4
https://blog.csdn.net/weixin_43362650/article/details/116864033
P128程序6.3 P129检测点6.1
P128
解题思路就是,将dw的数据先入栈,再出栈,实现数据的倒序排序。
先入栈保存原始的数据,数据此时已经是0123h在最下面,再出栈覆盖原dw内存地址的数据,按照出栈数据实现倒序排序。
P129 检测点6.1
https://blog.csdn.net/takashi77/article/details/108940638
这两个题目的要求是要将0:0~0:15内存单元中的数据改写到程序中的数据,需要读一下题。
首先,0:0~0:15的内存单元数据肯定就是ds中的数据,那么需要拷贝的地址就是 ds:0 ~ ds:15(0:0 ~ 0:15)
然后,改写到程序中意思是程序的内存地址,那么目的地址寄存器肯定就是cs,dw数据声明(程序偏移地址)从0开始,就是 cs:0 ~ cs:15
即:从ds015的内存地址拷贝到cs015的内存空间中。
1)
这里的mov ax, [bx]
等同于mov ax, ds:[bx]
,就已经拿到了ds中的数据,所以第一空填 mov cs:[bx], ax
。
将ax的值转移进cs中,因为bx都是两个寄存器的偏移地址,是等同的,所以下标拷贝对应的偏移位置也是一样的。
2)
答案
mov ax, cs
; 或者 mov sp, 36
mov sp, 24h
pop cs:[bx]
因为题目中的栈段写到了代码段中,所以和代码段共用地址,也就是在cs中。这里的第二步是拷贝到ss栈地址寄存器中,所以ss = cs,即mov ax, cs, mov ss, ax
。
sp = 24h是因为前面dw声明的内存位置(包含栈)已经有了24h,十进制是36,dw数据16个字节,栈20个字节, 16 + 20 = 36(24h)
和第一题一样,将数据入栈到栈里,再出栈,通过栈保存转移。
; 将ds:[bx]的数据入栈到ss:sp中,这里的ss:sp就是cs:sp
push [bx]
; 将ss:sp栈中的数据出栈到cs:[bx]中,实现数据转移
pop cs:[bx]
; 因为这里的bx偏移地址是ss(cs)&ds共用的(上述),在cs中也只是影响dw的声明数据段(会覆盖),不会影响栈内存空间。
add bx, 2