热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

实验4汇编应用程序和C语言程序反汇编分析

实验任务1:task1.asm代码:assumecs:code,ds:data;两个之间要用,分隔否则报错datasegmentdb'Welcometomasm!

实验任务1:

task1.asm代码:

assume cs:code,ds:data          ;两个之间要用 , 分隔否则报错
data segment
db 'Welcome to masm!'      ;数据段中保存显示的字符串
data ends
code segment
start: mov ax,data
mov ds,ax

mov ax,0b800h  
mov es,ax        ;es保存目标显存段地址
mov bx,720h       ;bx保存第一行目标显存偏移地址的起始地址
mov cx,16        ;cx保存循环次数,此处一共需要输入16个字符
mov si,0
mov di,0a0h       
s: mov al,ds:[si]      ;移入al,用以确保每次移入内存1个字节
mov es:[bx],al       ;偏移地址:bx——第一行
   mov es:[bx+di],al      ;偏移地址:bx+di——第二行(di=0a0h=160)
mov es:[bx+di+0a0h],al    ;偏移地址:bx+di+0a0h——第三行

inc bx      ;bx自增一次,接下来分别加入各行的属性控制
mov byte ptr es:[bx],02h           ;0 000 0 010 B —— 黑(000)底绿(010)字  
mov byte ptr es:[bx+di],24h          ;0 010 0 100 B —— 绿(010)底红(100)字
mov byte ptr es:[bx+di+0a0h],71h        ;0 111 0 001 B —— 白(111)底蓝(001)字
inc si      ;si自增继续读入数据段中下一个字符
inc bx      ;bx再次自增,指定下一个目标内存地址偏移
loop s
mov ah, 4ch
int 21h
code ends
end start

编译、连接,运行结果截图:

(1) 显示属性:

 使用8位(1字节)进行表示

 

 使用mov指令是时, 移入数据至内存空间,需要指明数据类型 否则报错  operand must have size

 (2)屏幕中央位置的计算:

一行显示80个字符,显示一个字符需要2字节(内容  属性),一行共160字节

正中间三行为Line 11、12、13;

目标显存第一个字符的偏移地址为:1760+(160/2 - 1)- 15 =  1824 = 0720H

第一行:0720H~073FH 之后两行对应位置的偏移量分别加上 160 (0a0H)和 320 (0a0H + 0a0H);

实验成功。

实验任务2:

   task2.asm源代码:

assume cs:code, ds:data
data segment
str db 'try', 0      ;str 'another try',0
data ends
code segment
start:
mov ax, data
mov ds, ax
mov si, offset str
mov al, 2          ;mov al,4
call printStr
mov ah, 4ch
int 21h
printStr:
push bx
push cx
push si
push di
mov bx, 0b800H
mov es, bx
mov di, 0
s: mov cl, [si]
mov ch, 0
jcxz over
mov ch, al
mov es:[di], cx
inc si
add di, 2
jmp s
over: pop di
pop si
pop cx
pop bx
ret
code ends
end start

(1)原始代码编译、连接,执行结果:

(2)修改:将代码中数据段中字符串修改为 :‘another try’,0

…………………………

data segment
str db 'another try', 0
data ends

…………………………

mov al,4      ;mov al,2

…………………………

编译、连接,执行结果:

问题:

1 assume cs:code, ds:data
2 data segment
3 str db 'another try', 0
4 data ends
5
6 code segment
7 start:
8 mov ax, data
9 mov ds, ax
10
11 mov si, offset str     ;str为数据段起始偏移地址 ——— 设置数据段入口参数
12 mov al, 4 ;设置字符显示属性  00000 100B——红色
13 call printStr
14
15 mov ah, 4ch
16 int 21h
17
18 printStr:
19 push bx
20 push cx
21 push si
22 push di
23
24 mov bx, 0b800H
25 mov es, bx
26 mov di, 0
27 s: mov cl, [si]   ;cl保存当前读入数据段中的字符; 
28 mov ch, 0      ;设置ch=0,若cl读入0,即已读入字符串末尾;则cx=0
29 jcxz over      ;当cx = 0 jcxz跳转条件成立,跳转至over处,即子程序执行结束
30 mov ch, al
31 mov es:[di], cx
32 inc si
33 add di, 2
34 jmp s
35
36 over: pop di
37 pop si
38 pop cx
39 pop bx
40 ret
41
42 code ends
43 end start

(3)基于运行结果,理解源代码:

组合使用转移指令call和ret实现子程序的原理与方法:

具体地,在line18-49中:

①line19-22,line36-39,这组对称使用的push、pop,这样用的目的是什么?

功能:子程序开始之前,将主程序中使用的保存着主程序参数的寄存器的值存入栈中,在子程序功能结束之后,恢复寄存器中参数;

目的:保持主干程序的参数在调用子程序前后一致;

由于寄存器数量有限,子程序在实现其功能时有可能会改变保存着主程序重要参数的寄存器的值,导致主程序执行出错;在子程序运行之前,先将寄存器值全部入栈,子程序调用完成后恢复寄存器值。无法预料子程序中会用到哪些寄存器,索性统一全部进行入栈,结束后出栈恢复的操作。

②line31的功能是什么?

 每次移入一个字数据cx至目标显存,cl:目标内容,ch:目标属性;

 

实验任务3:

 task3.asm源代码为:

assume cs:code, ds:data
data segment           ;数据段共占据20H个字节
x dw 1984        ;存储长度为一个字两字节,
str db 16 dup(0)    ;存储长度为一个字节,共16字节,两段数据共17字节,补全至32字节存储
data ends
code segment
start:
mov ax, data        
mov ds, ax         ;将ds段寄存器设置为数据段开始
mov ax, x          ;反汇编查看实际代码为:mov ax,[0000]    ds:[0000]=07C0
mov di, offset str     ;设置偏移量di,为后续保存结果设置入口参数  offset str = 0002
call num2str         
mov ah, 4ch
int 21h
num2str:
push ax             ;进入子程序先保存参数
push bx
push cx
push dx

mov cx, 0
mov bl, 10           ;设置除数,8位
s1:
div bl              ;被除数默认保存在AX中
inc cx              ;记录位数,作为s2中loop指令的循环次数
mov dl, ah            ;将AH中的余数移入dl
push dx              ;将DX入栈,(出栈入栈以字为单位
mov ah, 0            
cmp al, 0             ;若此次除法结果的商为0,表示已取到所有数字;cmp al,0  若al=0,指令执行后zf=1
jne s1               ;若zf=0,回到s1再次执行
s2:
pop dx               ;取出一个字
or dl, 30h            ;将dl中保存的数字转换为字符
mov [di], dl           ;[di]为str的起始偏移地址  将结果保存到str:依次为1 9 8 4  
inc di
    inc ax              ;依旧保存循环次数
loop s2              ;循环四次
mov cx, ax            ;赋给CX
   mov bx, 0b800H
    mov es, bx             ;es保存显存段地址
   mov al, 2             ;设置输出字符串属性值
    mov di, offset str        ;取需要复制的数据的起始偏移地址,段地址在ds中
    mov si, 0              ;目标显存的偏移地址
s3:    
     push cx                ;保存cx,因为代码中改变了其值
     mov cl, [di]            ;低位保存内容
     mov ch,al              ;高字节保存属性
     mov es:[si], cx           ;内容+属性入栈
     inc di                ;di加1,继续下一个字符
     add si, 2              ;目标地址偏移加2
pop cx                ;还原cx的值
loop s3


pop dx
pop cx
pop bx
pop ax
ret
code ends
end start

 

 运行结果:

 (1)查看程序段内容是否改变:

 已经成功转换为字符串,并保存在str开始的内存中;

(2)加入输出代码后能输出;

改变数字:结果如下,

输出成功。

实验任务4:

 task4.asm源代码:

1 assume cs:code, ds:data
2 data segment
3 str db 80 dup(?)
4 data ends
5
6 code segment
7 start:
8 mov ax, data
9 mov ds, ax
10 mov si, 0
11
12 s1:
13 mov ah, 1
14 int 21h
15 mov [si], al
16 cmp al, '#'
17 je next
18 inc si
19 jmp s1
20 next:
21 mov cx, si        ;确定输出时的循环次数
22 mov si, 0
23 s2: mov ah, 2
24 mov dl, [si]
25 int 21h
26 inc si
27 loop s2
28
29 mov ah, 4ch
30 int 21h
31 code ends
32 end start

运行结果:

 ①line12-19实现的功能:

当前输入字符不为‘#’时,持续从键盘读入字符并在屏幕上显示;

并将输入的字符保存在data段预留的内存中;

②line21-27实现的功能:

在屏幕上输出读入的字符(不包括最后的‘#’);

实验任务5:

反汇编代码:

#include
int sum(int,int);
int main() {
int a = 2, b = 7, c;
c = sum(a, b);
return 0;
}
int sum(int x, int y) {
return (x + y);
}

设置断点,开始调试,查看反汇编:

 

分析反汇编代码,从汇编的角度,观察高级语言中参数传递和返回值是通过什么实现

 ①高级语言中参数传递和返回值是通过什么实现的:通过寄存器和栈来实现;

此处为值传递,被调函数的形参作为被调函数的局部变量,在该函数的栈中开辟内存空间以存放主函数传递进来的实参值,对参数的操作不影响主函数实参的值。

②参数的入栈顺序:参数入栈根据参数列表中的顺序,从右往左;

③返回值的带回方式:结果保存在寄存器中带回。



推荐阅读
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 《2017年3月全国计算机等级考试二级C语言上机题库完全版》由会员分享,可在线阅读,更多相关《2017年3月全国计算机等级考试二级C语言上机题库完全版( ... [详细]
  • 本文为Codeforces 1294A题目的解析,主要讨论了Collecting Coins整除+不整除问题。文章详细介绍了题目的背景和要求,并给出了解题思路和代码实现。同时提供了在线测评地址和相关参考链接。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • OO第一单元自白:简单多项式导函数的设计与bug分析
    本文介绍了作者在学习OO的第一次作业中所遇到的问题及其解决方案。作者通过建立Multinomial和Monomial两个类来实现多项式和单项式,并通过append方法将单项式组合为多项式,并在此过程中合并同类项。作者还介绍了单项式和多项式的求导方法,并解释了如何利用正则表达式提取各个单项式并进行求导。同时,作者还对自己在输入合法性判断上的不足进行了bug分析,指出了自己在处理指数情况时出现的问题,并总结了被hack的原因。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
author-avatar
len1111_744
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有