鱼C论坛

 找回密码
 立即注册
查看: 3693|回复: 6

[已解决]为什么汇编指令在执行过程中会改变?

[复制链接]
发表于 2022-7-14 22:38:12 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2022-7-15 17:31 编辑

        根据调试信息,不难获取代码段与堆栈段所占用内存情况如下:
  1. 堆栈区域:076C0 ~ 076F0  长度 30H
  2. 代码区域: 076D0 ~ 076EB  长度 1BH
复制代码

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

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

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

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

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

  11. code segment para public 'code'
  12. start:  mov ax,c               ; 多余指令,可以删除
  13.         mov ss,ax              ; debug 时看看 ss 在被赋值前是否已经与 ax 相同?多余指令,可以删除
  14.         mov sp,400h            ; debug 时看看 sp 在被赋值前其值是否已经是 400h?多余指令,可以删除
  15.         mov ax,a               ; 这里应该成为第一条指令
  16.         mov es,ax
  17.         mov bx,0
  18.         mov cx,8
  19.         mov ax,02h
  20.         mov ax,4c00h
  21.         int 21h
  22. code ends
  23. end start
复制代码

        这样定义堆栈段,编译的时候,就不会再出现没有堆栈的警告信息,在跟踪的时候,也不会再出现代码被修改的问题了。
        堆栈必须定义足够大,因为不止我们自己的代码在用,调用 DOS、BIOS 功能时,操作系统也在使用,定义小了会给程序埋下隐患,可能危害程序的正常运行。你的程序在为 sp 赋值后,代码被改变,可是,代码却并没有使用堆栈,是不是很奇怪?这是因为堆栈在我们并不知情的情况下,已经被操作系统使用,由于被使用的堆栈区域与代码区域重合,从而,造成代码莫名其妙被修改的后果。
        
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-11-2 10:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表