debug 指令补充
在执行 d
命令时可以带地址参数 (段地址: 偏移地址),其中的段地址会先被送到 ds
寄存器,再交给处理器。
因此,d
命令也可以这样用: d SR:offset
(SR指段寄存器)
例如:
-r ds
:1000
-d ds:0 ;查看从 1000:0 开始的内存区间中的内容
-r ds
:1000
-d ds:10 18 ;查看 1000:10 ~ 1000:18 中的内容
-d cs:0 ;查看当前代码段中的指令代码
-d ss:0 ;查看当前栈段中的内容
当然 e
命令、a
命令和 u
命令也是一样的。
例如:
-r ds
:1000
-e ds:0 11 22 33 44 55 66 ;在从 1000:0 开始的内存区间中写入数据
-u cs:0 ;以汇编指令的形式,显示当前代码段中的代码,0 代码的偏移地址
-r ds
:1000
-a ds:0 ;以汇编指令的形式,向从 1000:0 开始的内存单元中写入指令
有趣的现象
在执行以下的代码时,你会发现 t
命令会不管用:
mov ax, 2000 ; 1
mov ss, ax ; 2
mov sp, 10 ; 3
mov ax, 3123 ; 4
push ax ; 5
mov ax, 3366 ; 6
push ax ; 7
单步执行结果如下图所示:
可见第 2 行和第 3 行代码一起执行了 (我这里与书本上的展示不同,可能与软件版本有关)。
具体是怎么回事以后深究,我们需要知道的是: 在执行修改 ss 寄存器的指令时,下一条指令会被一并执行。
实验
本实验为《汇编语言》(王爽著,第 3 版)第 74 页 实验任务
- 将下面的程序写入内存,执行并填空:
为了便于验证实验结果,对该实验做如下两点调整:
- 在使用
a
命令输入指令调试前,使用e
命令将内存单元0021:0
到0021:7
连续 8 个字节数据修改为30H
,31H
,32H
,33H
,34H
,35H
,36H
,37H
- 将该实验中第 1 行的
mov ax, ffff
改为mov ax, 0021
mov ax, 0021 mov ds, ax mov ax, 2200 mov ss, ax mov sp, 0100 mov ax, [0] ; ax = _3130_ add ax, [2] ; ax = _6462_ mov bx, [4] ; bx = _3534_ add bx, [6] ; bx = _6c6a_ push ax ; sp = _00fe_ ; 修改的内存单元的地址是 _220fe_ 内容为 _6462_ push bx ; sp = _00fc_ ; 修改的内存单元的地址是 _220fc_ 内容为 _6c6a_ pop ax ; sp = _00fe_ ; ax = _6c6a_ pop bx ; sp = _0100_ ; bx = _6462_ push [4] ; sp = _00fe_ ; 修改的内存单元的地址是 _220fe_ 内容为 _3534_ push [6] ; sp = _00fc_ ; 修改的内存单元的地址是 _220fc_ 内容为 _3736_
填空已经写进了注释,运行结果如下图所示:
这个实验在 FreeDOS 中会报错,如下图所示:
最后不得不用了 MS-DOS,我分析原因是 FreeDOS 不完全兼容 16 位汇编出现
operand size mismatch
- 在使用
- 为什么
2000:0
~2000:f
中的内容会发生改变?运行结果如下图所示:
仔细观察执行后
2000:a
到2000:d
内存中的数据,可见正好是依照小端法存储的cs
和ip
的值,据网上资料所说,这是对定义栈段时部分运行环境变量进行暂存,靠近栈顶的 10 个字节中的暂存数据分别是ss
、ip
、cs
等的值,是否正确我尚未考证,但应该与系统的调度有关。
我认为汇编是计算机专业的必修课,在计算机系统中也好,单独作为一门课程也罢,真正需要学习的不是怎么用,这是为了弥补一个计算机专业学生的基本常识。如果只是觉得什么东西有用而学它,那是没有回报的。如果你只看到一件事的1%,不代表你看到了它剩下的99%。在一切因素都不确定的情况下,能做好自己本分又有多少。干些什么吧,趁自己还年轻。
Invictus maneo.
原文地址:https://www.cnblogs.com/jordangong/p/9863597.html