[029][x86汇编语言]第十三章 习题:修改内核程序和用户程序,改由用户程序自行提供栈空间

学习笔记

《x86汇编语言:从实模式到保护模式》
https://www.jianshu.com/p/d481cb547e9f

答案参考

https://blog.csdn.net/longintchar/article/details/51167487?locationNum=5&fps=1

本章习题

  • 在本章中,用户程序只给出建议的栈大小,但并不提供栈空间。现在,修改内核程序和用户程序,改由用户程序自行提供栈空间。要求:栈段必须定义在用户程序之后。

习题解答

修改内核程序 c13_core.asm

 ;建立程序堆栈段描述符
         mov ecx,[edi+0x0c]                 ;4KB的倍率 
         mov ebx,0x000fffff
         sub ebx,ecx                        ;得到段界限
         
         mov eax,4096                        
         mul dword [edi+0x0c]  
         mov edx,edi
         add edx,[edi+0x08]
         add eax,edx                        ;得到栈的高端物理地址

         mov ecx,0x00c09600                 ;4KB粒度的堆栈段描述符
         call sys_routine_seg_sel:make_seg_descriptor
         call sys_routine_seg_sel:set_up_gdt_descriptor
         mov [edi+0x08],cx
  • 计算段界限
计算段界限

《x86汇编语言:从实模式到保护模式》 第237页

修改用户程序 c13.asm

usr_stack_len equ 1
usr_stack_cap equ usr_stack_len*0x1000 ; 0x1000 = 4096
     
;===============================================================================
SECTION header vstart=0

         program_length   dd program_end          ;程序总长度#0x00
         
         head_len         dd header_end           ;程序头部的长度#0x04

         stack_seg        dd section.stack.start                ;用于接收堆栈段选择子#0x08
         stack_len        dd usr_stack_len                      ;程序建议的堆栈大小#0x0c
                                                  ;以4KB为单位
                                                  
         prgentry         dd start                ;程序入口#0x10 
         code_seg         dd section.code.start   ;代码段位置#0x14
         code_len         dd code_end             ;代码段长度#0x18

         data_seg         dd section.data.start   ;数据段位置#0x1c
         data_len         dd data_end             ;数据段长度#0x20
             
;-------------------------------------------------------------------------------
         ;符号地址检索表
         salt_items       dd (header_end-salt)/256 ;#0x24
         
         salt:                                     ;#0x28
         PrintString      db  '@PrintString'
                     times 256-($-PrintString) db 0
                     
         TerminateProgram db  '@TerminateProgram'
                     times 256-($-TerminateProgram) db 0
                     
         ReadDiskData     db  '@ReadDiskData'
                     times 256-($-ReadDiskData) db 0
                 
header_end:
;===============================================================================
SECTION stack vstart=0
stack_start:        
        times usr_stack_cap db 0    ;4KB的栈空间
stack_end:

;===============================================================================
  • 增加两个常量 用户程序栈的大小(以4KB为单位)usr_stack_len 以及 用户程序栈的容量usr_stack_cap
  • 修改标号stack_seg 以及 stack_len 后面的初始值;
  • 增加段SECTION stack,这样就由用户程序自己给自己提供栈空间;

Bochs 调试

  • 从加载程序跳转到内核程序
由加载程序的
行数   汇编地址  机器码    汇编指令 
136 00000138 FF6F10     jmp far [edi+0x10]  

在 bochs使用
b 0x7d38
c
就可以跳转到 加载程序 转移控制权给 内核程序的这一条指令;

0x7d38  等于 0x7c00+0x138
  • 执行内核程序的指令
来到内核程序之后,遇到的第一条指令是:
行数    汇编地址  机器码      汇编指令
561 00000159 B930000000    mov ecx,core_data_seg_sel     

而这条指令的真实物理地址是 0x410a9

我希望直接跳到,加载完全部描述符的
这条指令:
   503 000000EB 66894F08            mov [edi+0x08],cx

经过换算,可以得出,目标的真实物理地址
应该是 0x4103b

因此,在bochs里面使用
b 0x4103b
c
就可以跳转到这条指令了。
  • 使用info gdt查看GDT的内容,看到 Expand-down字样说明加载栈段成功
    Expand-dwon字样说明这是向下生长的数据段即栈段.png
栈段都是Expand-down.png

Debug

1、调试用户程序的时候,将某个SECTION的标号当做是从整个程序开头的偏移量了

标记了vstart=0 说明标号的值是从段开始的偏移量

2、实际测试 push pop

  • 这里一开始忘记给字符串 message_test 最后加上 0 作为结尾,结果每次运行都死机,死机还死在不同的位置(就是显示的字符串数量完全不一样)
;===============================================================================
SECTION data vstart=0    
                         
         buffer times 1024 db  0         ;缓冲区

         message_1         db  0x0d,0x0a,0x0d,0x0a
                           db  '**********User program is runing**********'
                           db  0x0d,0x0a,0
         message_2         db  '  Disk data:',0x0d,0x0a,0

         message_test      db 0x0d,0x0a,0x0d,0x0a
                           db '>>>>>> test stack pass <<<<<<',0x0d,0x0a,0
data_end:

;===============================================================================

        ;>>>>>>>>>>>> TEST STACK <<<<<<<<<<<<<<<<<<<<<<
                push ecx
                
                mov ecx,1000
            testpush:
                push ebx
                loop testpush
            
                mov ecx,1000
            testpop:
                pop ebx
                loop testpop
                
                pop ecx
        
                
            mov ebx,message_test
            call far [fs:PrintString]

        ;>>>>>>>>>>>> TEST STACK <<<<<<<<<<<<<<<<<<<<<<

实际测试用户程序的栈 测试结果
  • 心得:以后如果要写有关测试的输出语句,就应该在代码可以正常运行的时候,先保证这条输出语句也可以正常运行,再去功能化新的代码,不然根本分不清是新代码的功能有缺陷还是输出语句本身错了,谁会想到一条简单的输出函数调用都会错,而且错是错在输出用的字符串这里,没错,这就是汇编。

完整源码

用户程序 c13.asm (第十三章 习题答案)

           ;代码清单13-3
         ;文件名:c13.asm
         ;文件说明:用户程序 
         ;创建日期:21:58 2018/6/4
     
usr_stack_len equ 1
usr_stack_cap equ usr_stack_len*0x1000 ; 0x1000 = 4096
     
;===============================================================================
SECTION header vstart=0

         program_length   dd program_end          ;程序总长度#0x00
         
         head_len         dd header_end           ;程序头部的长度#0x04

         stack_seg        dd section.stack.start                ;用于接收堆栈段选择子#0x08
         stack_len        dd usr_stack_len                      ;程序建议的堆栈大小#0x0c
                                                  ;以4KB为单位
                                                  
         prgentry         dd start                ;程序入口#0x10 
         code_seg         dd section.code.start   ;代码段位置#0x14
         code_len         dd code_end             ;代码段长度#0x18

         data_seg         dd section.data.start   ;数据段位置#0x1c
         data_len         dd data_end             ;数据段长度#0x20
             
;-------------------------------------------------------------------------------
         ;符号地址检索表
         salt_items       dd (header_end-salt)/256 ;#0x24
         
         salt:                                     ;#0x28
         PrintString      db  '@PrintString'
                     times 256-($-PrintString) db 0
                     
         TerminateProgram db  '@TerminateProgram'
                     times 256-($-TerminateProgram) db 0
                     
         ReadDiskData     db  '@ReadDiskData'
                     times 256-($-ReadDiskData) db 0
                 
header_end:
;===============================================================================
SECTION stack vstart=0
stack_start:        
        times usr_stack_cap db 0    ;4KB的栈空间
stack_end:

;===============================================================================
SECTION data vstart=0    
                         
         buffer times 1024 db  0         ;缓冲区

         message_1         db  0x0d,0x0a,0x0d,0x0a
                           db  '**********User program is runing**********'
                           db  0x0d,0x0a,0
         message_2         db  '  Disk data:',0x0d,0x0a,0

         message_test      db 0x0d,0x0a,0x0d,0x0a
                           db '>>>>>> test stack pass <<<<<<',0x0d,0x0a,0
data_end:

;===============================================================================
      [bits 32]
;===============================================================================
SECTION code vstart=0
start:
         mov eax,ds
         mov fs,eax
     
         mov eax,[stack_seg]
         mov ss,eax
         mov esp,0
     
         mov eax,[data_seg]
         mov ds,eax
     
         mov ebx,message_1
         call far [fs:PrintString]
     
         mov eax,100                         ;逻辑扇区号100
         mov ebx,buffer                      ;缓冲区偏移地址
         call far [fs:ReadDiskData]          ;段间调用
     
         mov ebx,message_2
         call far [fs:PrintString]
     
         mov ebx,buffer 
         call far [fs:PrintString]           ;too.
     
        
        ;>>>>>>>>>>>> TEST STACK <<<<<<<<<<<<<<<<<<<<<<
                push ecx
                
                mov ecx,1000
            testpush:
                push ebx
                loop testpush
            
                mov ecx,1000
            testpop:
                pop ebx
                loop testpop
                
                pop ecx
        
                
            mov ebx,message_test
            call far [fs:PrintString]

        ;>>>>>>>>>>>> TEST STACK <<<<<<<<<<<<<<<<<<<<<<


        jmp far [fs:TerminateProgram]       ;将控制权返回到系统 
         
         

      
code_end:

;===============================================================================
SECTION trail
;-------------------------------------------------------------------------------
program_end:
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容