SKY_DOR/cy 发表于 2022-7-14 22:38:11

为什么汇编指令在执行过程中会改变?

本帖最后由 SKY_DOR/cy 于 2022-7-14 22:39 编辑

assume cs:code,ss:c,ds:b,es:a
a segment
      db 1,2,3,4,5,6,7,8
a ends
b segment
      db 1,2,3,4,5,6,7,8
b ends
c segment
      db 0,0,0,0 , 0,0,0,0
c ends
code segment

start: mov ax,a
      mov es,ax
      mov ax,c
      mov ss,ax
      mov sp,30h
      mov bx,0
      mov cx,8

   mov ax,02h
   mov ax,4c00h
   int 21h

code ends
end start
上面是我写的汇编代码
编译出来的结果 076D:0016处的指令是:mov ax,4c00h




我执行完下面的代码段之后
mov ss,ax
mov sp,30h
076D:0016处的指令变为:ADD al,



想了很久一直想不通是什么原因,想向大家请教一下



jackz007 发表于 2022-7-14 22:38:12

本帖最后由 jackz007 于 2022-7-15 17:31 编辑

      根据调试信息,不难获取代码段与堆栈段所占用内存情况如下:
堆栈区域:076C0 ~ 076F0长度 30H
代码区域: 076D0 ~ 076EB长度 1BH
      这里的内存地址是 20 位绝对地址
      对于 exe 文件而言,其各个段所属的内存空间是不可以发生重叠的,不难看出,在本例中,堆栈段完全覆盖了代码段,整个代码段全部位于堆栈段内,这样,当堆栈中有数据存入时,就很容易破坏代码段的数据,这就是本例代码存在的问题。
      
      又是 X 爽教的,赶快换教材吧,其实,assume 伪指令一般是不需要声明堆栈段的,在程序代码中也无需为 ss、sp 赋初值,因为 exe 文件头中有专门的字段记载它们的数值,一个 exe 在加载进内存的时候,操作系统会根据文件头的信息自动设置这些寄存器的初始数值,根本不需要用代码去设置,我们要做的,是告诉编译程序,哪个是堆栈段就可以了。

assume cs:code , ds:b , es:a

a segment para public 'data'
      db 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8
a ends

b segment para public 'data'
      db 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8
b ends

c segment para stack 'stack'   ; 这样定义的堆栈段可以被编译器自动识别
      400h db dup(0)         ; 定义 400h 个字节的堆栈空间,并全部初始化为字节 00
c ends

code segment para public 'code'
start:mov ax,c               ; 多余指令,可以删除
      mov ss,ax            ; debug 时看看 ss 在被赋值前是否已经与 ax 相同?多余指令,可以删除
      mov sp,400h            ; debug 时看看 sp 在被赋值前其值是否已经是 400h?多余指令,可以删除
      mov ax,a               ; 这里应该成为第一条指令
      mov es,ax
      mov bx,0
      mov cx,8
      mov ax,02h
      mov ax,4c00h
      int 21h
code ends
end start
      这样定义堆栈段,编译的时候,就不会再出现没有堆栈的警告信息,在跟踪的时候,也不会再出现代码被修改的问题了。
      堆栈必须定义足够大,因为不止我们自己的代码在用,调用 DOS、BIOS 功能时,操作系统也在使用,定义小了会给程序埋下隐患,可能危害程序的正常运行。你的程序在为 sp 赋值后,代码被改变,可是,代码却并没有使用堆栈,是不是很奇怪?这是因为堆栈在我们并不知情的情况下,已经被操作系统使用,由于被使用的堆栈区域与代码区域重合,从而,造成代码莫名其妙被修改的后果。
      

人造人 发表于 2022-7-14 23:07:33

1.
mov sp,30h
你的堆栈定义了几个字节?
你使用了几个字节?
你堆栈定义了8个字节
你堆栈使用了30h个字节
8 != 30h

2.
es 和 ss 设置了,为什么不设置 ds ?

3. 我承认给程序中用到的变量、函数 这些取一个有意义的名字很难,但是你取的 abcd 这名字也太不负责任了吧

傻眼貓咪 发表于 2022-7-15 08:35:28

{:10_282:}

SKY_DOR/cy 发表于 2022-7-16 14:13:22

jackz007 发表于 2022-7-15 14:32
根据调试信息,不难获取代码段与堆栈段所占用内存情况如下:

      这里的内存地址是 20 位绝 ...

谢谢你详细、耐心的解答!阅读你的答案后调整代码,程序顺利跑通了!也让我收获了一个全新的知识点:操作系统会对栈空间的数据进行改写

SKY_DOR/cy 发表于 2022-7-16 14:18:35

人造人 发表于 2022-7-14 23:07
1.
mov sp,30h
你的堆栈定义了几个字节?


谢谢你的回答!你指出的问题是准确的
因为我在定位是哪句代码执行时导致问题的产生,所以就删了一部分不影响问题出现的语句,包括对ds的赋值
感谢你的提醒!我很赞同你的建议,在写程序应当取一个合适的名称。不过,因为我是做练习,对段的命名也是照抄书本,所以没特别留意。但是还是感谢你给予的提醒!
页: [1]
查看完整版本: 为什么汇编指令在执行过程中会改变?