鱼C论坛

 找回密码
 立即注册
查看: 6257|回复: 7

[汇编作业] 汇编语言_实验5(超详细)

[复制链接]
发表于 2021-2-5 22:53:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 635924705 于 2021-2-5 22:53 编辑

【手打不宜,错了勿喷,还请斧正,万分感谢,学习交流,共同进步】
【文中大部分数字都是16进制,我没加h,希望不影响大家阅读】
【文中个别不重要的机器码可能错了几个地方,因为有复制前面的,作者自查了一遍,还是可能有遗漏,我下次一定要发图片】
(1)
assume cs:code, ds:data, ss:stack

data segment
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data ends

stack segment
    dw 0,0,0,0,0,0,0,0
stack ends

code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,16        
        mov ax,data
        mov ds,ax
        push ds:[0]
        push ds:[2]
        pop  ds:[2]
        pop  ds:[0]                
        
        mov ax,4c00h
        int 21h
        
code ends

end start
首先代码输入没什么好说的,就是按着书上抄就行,注意不要打中文格式的字就行(我一开始逗号打成中文了,就报错了)
1.cpu执行程序,程序返回前,data数据段中的数据为多少?
cpu执行程序,程序返回前是哪个阶段,我一直很疑惑,我这里理解成debug 1.exe之后,没有运行程序的任何步骤之前(我的文件命名为1.asm所以编译链接之后就变成了1.exe)
此时用r查看寄存器状态如下:(我才发现我不能上传图片,只能手打,求赞,哭了 )
-R
AX=FFFF  BX=0000  CX=0042  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000  
DS=075A  ES=075A  SS=0769  CS=076C  IP=0000  NV UP EI PL NZ NA PO NC
076C:0000  B86B07            MOV    AX,076B
然后用u查看一下汇编语言命令,直接用u查不全,我们根据cs:ip自己查多一部分空间
-U 076c:0 25
076C:0000  B86B07         MOV    AX,076B
076C:0003  8ED0            MOV    SS,AX
076C:0005  BC1000         MOV    SP,0010
076C:0008  B86A07         MOV    AX,076A
076C:000B  8ED8            MOV    DS,AX
076C:000D  FF360000      PUSH   [0000]
076C:0011  FF360200      PUSH   [0002]
076C:0015  8F060200      POP     [0002]
076C:0019  8F060000      POP     [0000]
076C:001D  B8004C         MOV    AX,4C00
076C:0020  cd21             INT      21
076C:0022  0000             ADD     [BX+SI],AL
076C:0024  0000             ADD     [BX+SI],AL
(打完上面一串代码我就在思考,我是谁,我在干嘛了,我要不要试一下开个会员看能不能发图片
可以看到在1.asm文件中的data和stack这个两个字段被编译器替换成了076A(data)和076B(stack),感觉类似于c语言中的宏定义。首句assume中定义了data和stack这个两个字段,编译器识别并且赋值,然后替换代码段中所有的data和stack。
好吧,回归题目,此时data数据段中的数据为多少,data是076A,用d查看data段的内容
-d  076a:0
076A:0000  23  01  56  04  89  07  BC  0A-EF  0D  ED  0F  BA  0C  87  09                    #.V...........'
076A:0010  00  00  00  00  00  00  00  00-00  00  00  00  00  00  00  00                      ................(这个有多少点我也不清楚,乱打的,忽略就好)
(...原谅我打不下去了,用语言描述一下,这一行是076A:0020也就是076C:0000,也就是code段,也就是上面的代码的机器码,我就不多打一遍了,大家自行脑补一下下)
秉着严谨的态度,我用u指令看一下,课本给的数据是不是还可以翻译成指令
-u  076A:0
076A:0000  2301                   AND         AX,[BX+DI]
076A:0002  56                      PUSH        SI
076A:0003  0489                   ADD         AL,89
076A:0005  07                      POP          ES
076A:0006  BC0AEF               MOV         SP,EF0A
076A:0009  0DED0F               OR           AX,0FED
076A:000C  BA0C87               MOV         DX,870C
076A:000F  0900                   OR           [BX+SI],AX
076A:0011  0000                   ADD         [BX+SI],AX
076A:0013  0000                   ADD         [BX+SI],AX
076A:0015  0000                   ADD         [BX+SI],AX
(自闭ing )
书本给的数据果然可以翻译成指令,就是,嗯,,看不太懂这些指令想干嘛,不过不重要了,题目又不问这些,有想知道的就自行研究吧。
好,至此,data的内容和data段的内容我们都得出来了,应该是完成了第一问。

2.cpu执行程序,程序返回前,cs=_____,ss=_______,ds=_______。
嗯,就是抄寄存器状态呗,见第一问-r查看的内容。
cs=076C,ss=0769,ds=075A
在这里我们可以看到,这个程序默认的开头是数据段(psp),在075a,之后是栈段,栈的底层在0769,最后是代码段,在076c。
psp一共256个字节,低位是psp的开头指令(int 20啥的,感兴趣的可以自己看),最高位是栈的起始地址(栈是由高位向低位存储),个人感觉不安全,要是我栈段存300给字节,PSP的内容就会被覆盖掉。

3.设程序加载后,code段的段地址是X,则data段的地址为_______,stack段的地址为_________.
题目问的是真的模糊,如果问的是data和stack的值,那程序加载后,其实已经过了编译器data和stack就不存在了,debug里面可没有data和stack,只有被替换出来的值,如第一问,076A(data)和076B(stack)。那我权当她问的是ds和ss这两个段寄存器的段地址吧。
那就一步一步-t。(全抄太麻烦,我在汇编指令旁边标上ds和ss会变化的地方)
076C:0000  B86B07         MOV    AX,076B
076C:0003  8ED0            MOV    SS,AX                    ;ss:0769---》076b
076C:0005  BC1000         MOV    SP,0010
076C:0008  B86A07         MOV    AX,076A
076C:000B  8ED8            MOV    DS,AX                    ;ds:075a---》076a
076C:000D  FF360000      PUSH   [0000]
076C:0011  FF360200      PUSH   [0002]
076C:0015  8F060200      POP     [0002]
076C:0019  8F060000      POP     [0000]
076C:001D  B8004C         MOV    AX,4C00
076C:0020  cd21             INT      21
076C:0022  0000             ADD     [BX+SI],AL
076C:0024  0000             ADD     [BX+SI],AL
这里原状态DS=075A  SS=0769  CS=076c,075A:0-0769:0的15*16个字节是数据段(psp),0769:0-076c:0的3*16个字节是栈段,076c:0之后是代码段
编译器改为DS=076A  SS=076b  CS=076c,075A:0-076A:0的16*16个字节是psp,076A:0-076b:0的1*16个字节是数据段,076b:0-076c:0的1*16个字节是栈段,076c:0之后是代码段
(个人猜测,因为编译器不知道你要个什么段,所以,我们每声明一个段,编译器就自动给个n*16个字节的空间。因为这几个段我们存的数据都少于16个字节,所以统一为16给字节,如果我猜错了,欢迎大家帮助我改正,嘻嘻 )076C之后是代码段。

好,第一题写完了。(ps:写完第一题的我去看了看怎么升级,毕竟升级就能发图片,不用打字了。然后,我点开了VIP页面,刚刚想买,卧槽,家境贫寒告辞!! (其实也不算贵,因为教程很棒,但是,无奈我更穷),,,,,,,求精华吧,就想升级不用打字,嘤嘤嘤

(2)
assume cs:code, ds:data, ss:stack

data segment
    dw 0123h,0456h
data ends

stack segment
    dw 0,0
stack ends

code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,16
        mov ax,data
        mov ds,ax
        push ds:[0]
        push ds:[2]
        pop  ds:[2]
        pop  ds:[0]                
        
        mov ax,4c00h
        int 21h
        
code ends

end start
代码没啥好说的,抄一遍,代码和第一题很像,就删了一点点,不过这个题实在逗我吗,基本上长的一模一样,
1.cpu执行程序,程序返回前,data数据段中的数据为多少?
(由于和第一题相似度过高,第一题我讲的很详细,所以,我就重点写不一样的地方)、
Data被替换为076a,
用r查看寄存器状态发现和第一题一样
-r
AX=FFFF  BX=0000  CX=0042  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000  
DS=075A  ES=075A  SS=0769  CS=076C  IP=0000  NV UP EI PL NZ NA PO NC
076C:0000  B86B07            MOV    AX,076B
用-d查看data段的内容
-d  076a:0
076A:0000  23  01  56  04  00  00  00  00-00  00  00  00  00  00  00  00                    #.V...........'
076A:0010  00  00  00  00  00  00  00  00-00  00  00  00  00  00  00  00                      ................(一堆数目不明的点)
后面也和第一题一样是code段的指令,我就同样省略了。
data的内容和预估一样,就是前4个字节有

2.cpu执行程序,程序返回前,cs=_____,ss=_______,ds=_______。
由-r的内容,直接填,和第一题的值一样
cs=076C,ss=0769,ds=075A

3.设程序加载后,code段的段地址是X,则data段的地址为_______,stack段的地址为_________.
代码段和第一题一模一样,还是直接在代码段上写变化
一步一步-t
076C:0000  B86B07         MOV    AX,076B
076C:0003  8ED0            MOV    SS,AX                    ;ss:0769---》076b
076C:0005  BC1000         MOV    SP,0010
076C:0008  B86A07         MOV    AX,076A
076C:000B  8ED8            MOV    DS,AX                    ;ds:075a---》076a
076C:000D  FF360000      PUSH   [0000]
076C:0011  FF360200      PUSH   [0002]
076C:0015  8F060200      POP     [0002]
076C:0019  8F060000      POP     [0000]
076C:001D  B8004C         MOV    AX,4C00
076C:0020  cd21             INT      21
076C:0022  0000             ADD     [BX+SI],AL
076C:0024  0000             ADD     [BX+SI],AL
同第一题,ds由075a变成076a,ss由0769变成076b, CS是076C始终不变。那data就是X-2,stack就是X-1

4.对于如下定义的段
name segment
...
name  ends
如果段中的数据占n个字节,则程序加载后,该段实际占有的空间为______.

(终于有一题不一样了)
这一问的问题,我们在第一题就有过猜想,就是n*16个字节,现在已经验证了16,10,4,2个字节都是16个字节的空间,所以,我们来一个20给字节的声明,看一下编译器给多少空间就知道,我们的猜想对不对了。
懒惰的我,就不改段名字了,直接在data段做实验。
assume cs:code, ds:data, ss:stack

data segment
    dw 0123h,0456h,0123h,0456h,0123h,0456h,0123h,0456h,0123h,0456h
data ends

stack segment
    dw 0,0
stack ends

code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,16
        mov ax,data
        mov ds,ax
        push ds:[0]
        push ds:[2]
        pop  ds:[2]
        pop  ds:[0]                
        
        mov ax,4c00h
        int 21h
        
code ends

end start
查看寄存器状态
-r
AX=FFFF  BX=0000  CX=0052  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000  
DS=075A  ES=075A  SS=0769  CS=076D  IP=0000  NV UP EI PL NZ NA PO NC
076d:0000  B86c07            MOV    AX,076C
查看汇编指令
-U 076d:0 25
076D:0000  B86c07         MOV    AX,076C
076D:0003  8ED0            MOV    SS,AX                ;ss:0769---》076C
076D:0005  BC1000         MOV    SP,0010
076D:0008  B86A07         MOV    AX,076A
076D:000B  8ED8            MOV    DS,AX                ;ds:075a---》076a
076D:000D  FF360000      PUSH   [0000]
076D:0011  FF360200      PUSH   [0002]
076D:0015  8F060200      POP     [0002]
076D:0019  8F060000      POP     [0000]
076D:001D  B8004C         MOV    AX,4C00
076D:0020  cd21             INT      21
076D:0022  0000             ADD     [BX+SI],AL
076D:0024  0000             ADD     [BX+SI],AL
这里原状态DS=075A  SS=0769  CS=076D,075A:0-0769:0的15*16个字节是数据段(psp),0769:0-076D:0的4*16个字节是栈段,076D:0之后是代码段
编译器改为DS=076A  SS=076C  CS=076D,075A:0-076A:0的16*16个字节是psp,076A:0-076C:0的2*16个字节是数据段,076C:0-076D:0的1*16个字节是栈段,076D:0之后是代码段
验证,我们的猜想应该是对的,debug,会把ds指向psp开始,ss指向psp的15*16个字节之后,小甲鱼老师说psp是16*16个字节,所以初始状态,PSP末尾的16个字节是栈段的。PSP和代码段中间有n*16个字节。n的值是每一段的数据的个数除以16然后向上取整,最后求和。编译器的话,会保护psp,将psp的16*16个字节保护,ds指向PSP之后,ss指向ds之后,根据其数据的个数,划分n*16个字节的空间)


(3)
assume cs:code, ds:data, ss:stack

code segment
start:  mov ax,stack
        mov ss,ax
                mov sp,16
                mov ax,data
                mov ds,ax
                push ds:[0]
        push ds:[2]
        pop  ds:[2]
        pop  ds:[0]                
        
        mov ax,4c00h
        int 21h
        
code ends

data segment
    dw 0123h,0456h
data ends

stack segment
    dw 0,0
stack ends

end start
代码直接抄,没啥好说的,题目还是一样的,我仿佛知道这个题目是什么意思了,就是想让我们知道编译器和debug的运转
1.cpu执行程序,程序返回前,data数据段中的数据为多少?
Data被替换为076d,
用r查看寄存器
-r
AX=FFFF  BX=0000  CX=0044  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000  
DS=075A  ES=075A  SS=0769  CS=076a  IP=0000  NV UP EI PL NZ NA PO NC
076a:0000  B86e07            MOV    AX,076e
用-d查看data段的内容
-d  076d:0
076A:0000  23  01  56  04  00  00  00  00-00  00  00  00  00  00  00  00                    #.V...........'
076A:0010  00  00  00  00  00  00  00  00-00  00  00  00  00  00  00  00                      ................(一堆数目不明的点)
后面都是00
data的内容和预估一样,就是前4个字节有

2.cpu执行程序,程序返回前,cs=_____,ss=_______,ds=_______。
由-r的内容,直接填
cs=076a,ss=0769,ds=075A

3.设程序加载后,code段的段地址是X,则data段的地址为_______,stack段的地址为_________.
代码段和,还是直接在代码段上写变化
一步一步-t
076a:0000  B86e07         MOV    AX,076e
076a:0003  8ED0            MOV    SS,AX                    ;ss:0769---》076b
076a:0005  BC1000         MOV    SP,0010
076a:0008  B86d07         MOV    AX,076d
076a:000B  8ED8            MOV    DS,AX                    ;ds:075a---》076a
076a:000D  FF360000      PUSH   [0000]
076a:0011  FF360200      PUSH   [0002]
076a:0015  8F060200      POP     [0002]
076a:0019  8F060000      POP     [0000]
076a:001D  B8004C         MOV    AX,4C00
076a:0020  cd21             INT      21
076a:0022  0000             ADD     [BX+SI],AL
076a:0024  0000             ADD     [BX+SI],AL
这里原状态DS=075A  SS=0769  CS=076a,075A:0-0769:0的15*16个字节是数据段(psp),0769:0-076a:0的16个字节是栈段,076a之后是代码段,
编译器改为DS=076d  SS=076e  CS=076a,075A:0-0769:0的16*16个字节是psp,076A:0-076d:0的3*16个字节是代码段,076d:0-076e:0的1*16个字节是数据段,076e:0之后是栈段
由此,我们可以看出来,段的顺序和我们编程的顺序是一样的,因为此题的栈段和数据段的编程在后面,所以,psp和代码段中间只有16个字节的初始的栈段。
联想到编译和链接文件时,会警告没有栈段,所以,我感觉没有栈段的时候,ss才会指向psp的后16位
得出,data段的地址为x+3,stack段的地址为x+4


(4)
不声明代码段入口的话,只有(3)的程序能正常运行,因为(3)的程序,代码段在最前面,cs:ip一开始就会指向这一段。


(5)
assume cs:code

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        

d segment              ;我用c做段名就报错,无奈,我改成了d,求大佬帮我解答why
    db 0,0,0,0,0,0,0,0
d ends
        
code segment
start:                  
            mov ax,d
                mov ds,ax      ;将d的段地址给ds
                
                mov ax,a
                mov es,ax      ;将a的段地址给es
                
                mov bx,0
                mov cx,8
   s1:  mov al,es:[bx]   
        mov [bx],al           ;将a段的值给d段,不用中转al会报错,不能用ax因为ax是2个字节,每个地址只有一个字节,可能出现未知错误
        inc bl
        loop s1
            
        mov ax,b
        mov es,ax      ;将b的段地址给es
                
           mov bx,0
        mov cx,8
   s2:  mov al,es:[bx]     
        add [bx],al             ;将b段的值加给d段
        inc bl
        loop s2
        
        mov ax,4c00h
        int 21h
        
code ends

end start
经检验,答案正确

(6)
assume cs:code

a segment
    dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends

b segment
    dw 0,0,0,0,0,0,0,0
b ends        
        
code segment
start:  mov ax,b      ;把b段视为栈空间
          mov ss,ax
          mov sp,10h   ;直接给b段的末尾地址给sp                
        
          mov ax,a
            mov ds,ax     ;将a段的地址给ds
                
          mov bx,0
          mov cx,8
      s:  push [bx]    ;将a段前8个数据入栈
          add bx,2     ;字型数据加2,两个inc是4个十六进制的代码,而add是3个,所以用add,省空间
          loop s
        
          mov ax,4c00h
          int 21h
        
code ends

end start
经检验,答案正确
[u]欢迎留言交流[/u]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-3-19 18:15:52 | 显示全部楼层
前面三道题你的理解有误 程序返回前指的是 debug -t单步运行到下一步执行 int 这一步。。运行了int就是返回了  N个字节占有空间应该是 16X( N/16 +1 )
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-3-30 15:21:38 | 显示全部楼层
最后一问,你只push入栈   逆序排列你没写
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-3-31 10:58:37 | 显示全部楼层
狂热终结者 发表于 2021-3-30 15:21
最后一问,你只push入栈   逆序排列你没写

这个东西,我当时想的是,因为出栈就是逆序的,就没反着入栈,可能当时理解错了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-30 16:50:06 | 显示全部楼层
5.5 其实用一次循环就可以解决,并且a & b端数据重复了,可以double a的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-3 12:27:50 | 显示全部楼层
谢谢楼主,楼主辛苦了,在下佩服,不给截图着实可恶。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 01:58:21 | 显示全部楼层
good !!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-20 21:32:33 | 显示全部楼层
第五题确实坑爹, c不行,改成其他的才行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-22 04:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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