assume cs:codesg
codesg segment
start: mov ax, 2000H
mov ds, ax
mov bx, 0
s: mov cl, [bx]
mov ch, 0
inc cx
inc bx
loop s
ok: dec bx
mov dx, bx
mov ax, 4c00h
int 21h
codesg ends
从代码看,应该是这样去分析的,首先程序的入口在start指向的地方,也就是mov ax,0这里,而不是一开始的退出程序的两条语句。
接着两条nop,各占1个字节。
然后mov di,offset s 这句是往di寄存器传递s 的偏移地址;
然后 mov si,offset s2,这句是王寄存器si传递s2的偏移地址
然后mov ax,cs:[si],所以ax保存了执行s2的指针地址。
mov cs:[di] ,ax 然后把s2的执行地址给了cs:[di]这个内存位置。
这里重点提一下s2:jmp short s1,这里从效果看,下一步就是要执行s1 段的代码。而机器指令EBF6,将被拷贝给cs:[di]的内存这里。而EBF6的效果实际上是往回跳10个字节( s1这里mov ax,0 占3个字节,int 21h 占2个字节, mov ax,0占3个字节,这样就是8个字节。而s2的jmp short s1本身占2个字节。这句执行完了,再回去10个字节,刚好就是s1的位置)
所以当EBF6拷贝给cs:[di]后,相当于cs:[di]实际保存了s的执行地址,所以是把EBF6这条机器指令拷贝给了s的nop nop这里。而EBF6的实际意思是往回跳10个字节,而不是字面的jmp short s1的意思,也就是不会跳下去执行s1,而是跳回去10个字节
这样计算下来EBF6本身2个字节,mov ax, 4c00h 3个字节, int 21h 2个字节 , mov ax, 0 3个字节,一共就是10个字节。所以执行完s段的代码后,指针就到了mov ax,4c00h这里。所以程序就正常退出了。
————————————————
版权声明:本文为CSDN博主「自觉的数字公民杨某某」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_47161778/article/details/125285200
assume cs:codesg ds:datasg
datasg segment
db 'Welcome to masm!'
db 2H, 24H, 71H ;字符串属性值
datasg ends
stack segment
dw 8 dup (0)
stack ends
codesg segment
start: mov ax, stack
mov ss, ax
mov sp, 10h
mov ax, datasg
mov ds, ax
mov bx, 0
mov ax, 0B800H
mov es, ax ;80×25彩色字符模式显示缓冲区段地址送入es
mov di, 10H ;字符串和颜色都是用这个偏移
mov cx 3
s0: push cx
mov ah, ds:[di]
push di
mov di, 0
mov si, 0
mov cx, 16
s: mov al, ds:[di]
mov es:[bx+si], al
mov es:[bx+si+1], ah
add si, 2
inc di
loop s
pop di
inc di
pop cx
add bxm 0a0h ;换行,每行80字符,160个字节
loop s0
all: jmp short all ;一直循环,为了看效果
mov ax, 4c00h
int 21h
codesg ends
end start