实验任务1
代码功能简析
输出两行1 9 3or 30h
是为了转换为\(ASCII\)码输出。 \(30h\) 是ASCII中 \('0'\) 的编号,其二进制形式为:\(0011 0000\) ,所以or上一个 \(30h\) 表示输出从'0'开始偏移量为1 9 3的数字
如果 or 61h
,则输出的是偏移量减去 \(1\) 的小写字母。( \(61h\) 是 \(0110 0001\) ,从1开始)$
是预定义符号,表示当前的偏移地址,使用 jmp $
,可以进入死循环。
问题1
反汇编查看机器码,可以看到其机器码为 \(E2F2\)
\(E2\) 表示LOOP
\(F0\) 是补码形式的位移量, \(F2\) 转换为二进制为 \(11110010\)
将其转换为原码 \(1!(1110010-1) = 1!(1110001) = 10001110 = -8+-4+-2=-14\)
所以其位移量为 \(-14\) 。当前ip为 \(0x19\) ,即 \(25\) ,\(25-14=11\)
但是s1处的偏移量为 \(D\) ,即 \(13\) 。
所以整个转移的过程如下
ip指向 \(25\) 偏移处的指令,先取指令,然后ip自动 \(+2\) ,变为 \(27\) ,然后执行指令的过程中,将ip减去 \(14\) ,得到 \(13\) ,那么下一条要执行的指令就在偏移量为 \(13\) 的地方,即s1标号处。
问题2
重复问题1的操作步骤。
\(F0\) 的二进制形式为: \(11110000\)
得到其原码: \(1!(1110000-1) = 1!(1101111) = 10010000 = -16\)
为什么指令数量相同,但是位移量不同?原因出在inc
和add
的指令占字节数不同。8086汇编采用动态指令长度,所以每条指令的长度都不是相同的。所以这里会有位移量的不同。
CPU计算得到s2之后指令的地址方式和问题1一样,这里不重复描述。
实验任务2
代码简析
assume cs:code, ds:data
data segment
dw 200h,0h,230h,0h
data ends
stack segment
db 16 dup(0)
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov word ptr ds:[0],offset s1
mov word ptr ds:[2],offset s2
mov ds:[4],cs
mov ax,stack
mov ss,ax
mov sp,16
call word ptr ds:[0]
;push ip
;jmp word ptr ds:[0]
s1: pop ax
;(ax) = stack.top() = offset line23 + size(line23) = offset s1
call dword ptr ds:[2]
;push cs
;push ip
;jmp dword ptr ds:[2]
s2: pop bx
;(bx) = stack.top() = offset line28 + size(line28) = offset s2
pop cx
;(bx) = stack.top() = cs = code
mov ah,4ch
int 21h
code ends
end start