王爽 汇编语言个人疑问汇总第五篇
目录
第九章
实验8 分析一个奇怪的程序
原程序
assume cs:codesg
codesg segment
mov ax,4c00h
int 21h
start:
mov ax,0
s:
nop ;该指令不会产生任何的效果
nop ; 该指令不会产生任何的效果
mov di,offset s ; s标号第一条指令的地址给di
mov si,offset s2 ;s2标号第一条指令地址给si
mov ax,cs:[si] ; cs:[si] 赋值给ax寄存器
mov cs:[di],ax ; ax赋值给cs:[di]
s0:
jmp short s ; 段内短转移,转移到标号处执行指令
s1:
mov ax,0
int 21h
mov ax,0
s2:
jmp short s1 ; 段内短转移,转移到标号处执行指令
nop
codesg ends
end start
程序分析
- 我们来debug下。
- 我们输入
t
,在观察cs段寄存器
很明显看到偏移地址0008的指令变成了
JMP 0000
(nop 只占一个字节, 因此两个 nop 被完全替代)。
毫无疑问就是
mov cs:[di],ax
这段代码改变的。
还有个疑问,为什么是JMP 0000呢?
mov si,offset s2
是指向s2
代码段第一条指令的,那么应该是jmp short s1
执行s1
代码段呀。
mov cs:[di], ax
后,可以暂且认为 cs:0008现在指令是jmp short s1
机器码是EBF6
。
注意:
jmp short
是段内短转移,求的是相对位置。F6就是-10,-10
是F6
补码形式(EB代表jmp指令,F6代表了自此偏移地址开始,向前偏移10个字节),所以从0008
位置向前偏移10个字节地址是0000
。
总结
jmp short xxx
是段内短转移,注意求的是相对位置,这段代码在不同的位置效果也不一样。
实验9 根据材料编程
assume cs:code
data segment
db 'welcome to masm!'
db 01110001b ; 白底蓝字 71H
db 00100100b ; 绿底红字 24H
db 00000010b ; 黑底绿字 02H
data ends
stack segment
dw 8 dup (0)
stack ends
code segment
start: mov ax,data
mov ds,ax ; data段指向ds段寄存器
mov ax,stack
mov ss,ax ; stack段指向ss段寄存器
mov sp,16
mov ax,0b800h
mov es,ax ; 显示缓冲区指向es段寄存器
mov si,06e0h ; 字符串从哪个位置开始显示
mov cx,3 ; 循环次数
s0: mov bx,cx
mov ah,[bx+15] ; 读取行的颜色,ax寄存器的高位存颜色; 黑底绿字 02H 、 绿底红字 24H 、白底蓝字 71H
mov bx,40h ; 在一行哪个位置开始
push cx ; 外层循环暂存cx,放到栈中
mov di,0 ; 第0字节开始
mov cx,16 ; 内循环次数 16,也就是 welcome to masm! 的长度
s: mov al,[di] ; 读取字符,ax寄存器的低位存字符
mov es:[bx+si],ax ; 写入字符
inc di ; 下一个字节
add bx,2 ; 下一个字
loop s ; 内循环,显示一行的数据
add si,0a0h ; next row 下一行,作用就是换行
pop cx ; 将栈中数据弹出给cx,外层循环使用
loop s0 ; 外循环,显示下一行的数据
mov ax,4c00h
int 21h
code ends
end start
第十章
检测点10.2 下面的程序执行后,ax中的数值为多少?
mov ax,0 ;读取此条指令后IP=3
call s ;读取此条指令后IP=6 , 执行call 标号时,相当于
;push IP
;jmp near ptr 标号
; 此时将6压入栈
; 下一步转移到s段
inc ax
s: pop ax ; 取出栈中数据赋值给ax寄存器,为0006H
- 关于
mov ax,0
我们IP的值=3,参考书上2.11 修改CS、IP指令
就知道了。
检测点10.3 下面的程序执行后,ax中的数值为多少?
内存地址 机器指令 汇编指令
1000:0 b8 00 00 mov ax,0 ; 读入这条指令 IP=3
1000:3 9A 09 00 00 10 call far ptr s ; 读入这条指令 IP=8
; call far ptr 标号 时相当于
; push CS
; push IP
; jmp far ptr 标号
1000:8 40 inc ax
1000:9 50 s:pop ax ; 按照栈先入后出的特性,第一次pop取出的是IP的值,为8,传送给ax寄存器
add ax,ax ; 8H + 8H = 10H
pop bx ; 按照栈先入后出的特性,第二次pop取出的是CS的值,CS的值题目已经给出了,是1000H,传送给bx寄存器
add ax,bx ; 1000H + 10H = 1010H
AX = 1010H
- 关于
mov ax,0
我们IP的值=3,参考书上2.11 修改CS、IP指令
就知道了。
检测点10.4 下面的程序执行后,ax中的数值为多少?
内存地址 机器码 汇编指令 执行后情况
1000:0 b8 06 00 mov ax,6 ; 读入这条指令 IP=3
1000:3 ff d0 call ax ; 读入这条指令 IP=5
; call 16位reg 相当于
;push IP ,push 5
;jmp 16位reg ,jmp 6
1000:5 40 inc ax ; 未执行
1000:6 58 mov bp,sp ; (bp) = (sp)
add ax,[bp] ;相当于add ax,[bp], bp就是sp,sp默认段地址ss,所以即把栈顶元素弹出和AX相加 ,6+5=11H
- 关于
mov ax,6
我们IP的值=3,参考书上2.11 修改CS、IP指令
就知道了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话