1)
内存位置 0x0150 和 0x154 中的 64 位整数
这不是非常准确的任务描述,64b 整数位于内存中从 0x0150 到 0x0157 的位置(总共 8 个字节)。该描述听起来像是默认的内存单元dword
使用(32 位),这在 16b 实模式下并不是非常合理的默认数据大小。
2) mov ax,0x0150
不从内存加载值,而是加载该常量0x0150
into ax
。如果要从内存加载实际值,则必须取消引用该内存地址,例如:
mov si,0x0150 ; set si to contain address of input number1
mov ax,[si] ; load least significant 16b word (LSW) of it into ax
; you can even use absolute addressing like:
mov ax,[0x0150] ; usually not practical, but possible
现在,如果您想要放置所有字的所有地址(将使用 3 * 4 个字的内存,num1、num2 和结果,所有这些都是 4 个字长),您很快就会用完寄存器。但实际上你可以在 16b 模式下使用相对寻址,所以这是可能的:
mov si,0x0150 ; set si to contain address of input number1
mov ax,[si]
mov bx,[si+2]
mov cx,[si+4]
mov dx,[si+6]
; here dx:cx:bx:ax concatenated into single 64b number contains the number1
但是数字 2 也可以通过数字 1 的基地址来寻址,因此您也可以继续进行减法:
sub ax,[si+0x10] ; subtraction of LSW, ignoring CF (borrow)
sbb bx,[si+0x12] ; continuing by subtracting adjoining 16 bits
; but this time CF will affect the result, to make any "borrowing"
; happening while subtracting the LSW to propagate into upper 16 bits
... etc..
关于评论中的问题...CF修改的结果已经存储在bx
,旧的CF丢失,CF包含新的“借用”bx - [0x162] - old_borrow
. You can如果你愿意,可以将 CF 存储在某处,CPU 有指令来检测/存储/设置 CF 的值,但是使用数字,一旦你计算出 15 - 8 就是 7,7 就是最终的,你不需要记住你确实借了“ 1" 从 5 中减去 8。
相对于 num1 地址,结果地址也很容易计算,因此您可以将结果存储回内存中
mov [si+0x20],ax ; 0x0150 + 0x20 = 0x0170
mov [si+0x22],bx
...
我基本上给了你整个解决方案:/ ...所以让我们至少添加一些更多信息,让你稍微解决一下。
您可以执行相同的操作,而无需使用 4 个 16b 寄存器来保存单个 64b 值,例如:
mov ax,[si]
sub ax,[si+0x10]
mov [si+0x20],ax
mov ax,[si+2]
sbb ax,[si+0x10+2]
mov [si+0x20+2],ax
...
看完这个,你可能会有一个好主意,怎么样:
mov ax,[si]
sub ax,[si+0x10]
mov [si+0x20],ax
add si,2 ; adjust rather base pointer then changing all those offsets
mov ax,[si]
sbb ax,[si+0x10]
mov [si+0x20],ax
...
有效吗?不再。这add si,2
会修改CF,所以接下来sbb
不“继续”减法。这里要吸取的教训是,您应该经常查看说明参考指南以获取详细信息。描述,包括它确实影响哪些标志。对于 x86 - 一些指令可能会让您感到惊讶,例如上面的代码修改为:
mov ax,[si]
sub ax,[si+0x10]
mov [si+0x20],ax
inc si ; adjust base pointer
inc si
mov ax,[si]
sbb ax,[si+0x10]
mov [si+0x20],ax
...
会起作用,因为inc
不影响CF,仅修改其他算术标志。
在不修改任何标志的情况下将两个添加到有效寻址寄存器的另一种方法是lea si,[si+2]
.
BTW dosbox 默认模拟 386+,所以你甚至可以在 16b 实模式下使用:
mov si,0x0150
mov eax,[si]
mov ebx,[si+4] ; ebx:eax = 64b number1 (note +4 this time)
sub eax,[si+0x10]
sbb ebx,[si+0x14] ; ebx:eax = (number1 - number2)
mov [si+0x20],eax
...
除非您被迫只能使用 8086 (80286) 指令集,否则 80386 CPU 会引入 32 位寄存器。