【汇编随笔】王爽《汇编语言(第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是最大了,只能往下调整。

  1. 20000H - FFFFH = 10001H,十进制是 65537,除以 10H 有小数所以不是倍数。
  2. 20000H - FFFEH = 10002H,十进制是 65538,除以 10H 有小数所以不是倍数。
  3. 20000H - FFFDH = 10003H,十进制是 65539,除以 10H 有小数所以不是倍数。
  4. ...
  5. 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
posted @ 2023-07-31 11:59  阿初  阅读(76)  评论(0编辑  收藏  举报