本文已参与「新人创作礼」活动,一起开启掘金创作之路。
声明 某小白在群内找了一道题,关于汇编的一个很简单的题,然后让分析过程,之后解答出了一个题,然后我就看了一下,发现有一些我确实不怎么知道,所以上网查了许多东西,然后记录下来
首先,看一下题目吧(来源:www.chegg.com/homework-he… 为了方便大家阅读,我已经把注释写上了 带注释的asm链接:pan.baidu.com/s/1svcIP9nU… 提取码:jnie
; READING CODE - STACK
; ;list the output of the following program assuming the input is as follows:
; 101
; 232
; 48
; 17
include PCMAC.INC ;Add the PAMAC.INC to the source file ( call library)
NEWLINE EQU _PutCh 13, 10 ; Equivalent to '\n' newline
.MODEL SMALL
.STACK 100h ; The first address of the stack
.DATA ; Data segment
Message1 DB 'Total sold today, $' ; Message1 for the convenience of the following calls
Message2 DB ' , is: $' ; Message2
.CODE ; Code segment Indicates the beginning of the code segment
EXTERN GetDec: NEAR, PutDec:NEAR ; Declare a function GetDec -> input PutDec -> output
Main PROC ;begin
mov ax, @data
mov ds, ax
_GetDate ;time
push cx ;
push dx
push dx
call SubInput ;send control to subprocedure
mov bx, ax
_PutStr Message1 ;output 'Total sold today,'
pop dx ;pop dx
mov al, dh
mov ah, 0 ;just assign dh to ax (numerical value)
call PutDec ;output dh
_PutCh '/' ;output '/'
pop dx
mov al, dl
mov ah, 0
call PutDec
_PutCh '/' ;the same as above
pop cx
mov ax, cx
call PutDec
_PutStr Message2 ;output ' , is:' here! 'Total sold today, 11/26/2019 , is:'
mov ax, bx
call PutDec ;'Total sold today, 11/26/2019 , is: 398'
NEWLINE ; newline
mov al, 0 ; Return code of 0
mov ah, 4ch ; Exit back to MSDOS
int 21h
Main ENDP
.Data ; re-enter the data segment for this procedure
MessageSub DB 'Enter a number $'
Mystery DW ?
.CODE ; return to coding
SubInput PROC
mov cx, 4 ;Read four values in a loop
myLoop:
_PutStr MessageSub
call GetDec
add Mystery, ax ; sum++
dec cx
jnz myLoop
mov ax, Mystery
ret
SubInput ENDP
END Main ; Tells where to start execution
然后让回答出几个问题:
1- What is the purpose of line 8?
Add the PAMAC.INC to the source file ( call library)
2- Why do we include line 18?
Indicates the beginning of the code segment
3- What can we replace lines 21 and 22 with?
mov bx , @data mov ds , bx
4- What registers does _GetDate use? (Hint: find it in the book)
*cx , dx , ss
5- What register is at the top of the stack right after line 26?
dx
6- Why are we pushing dx twice?
Lines 31 and 36 use the dx ,so we should have two dx to pop
7- What register is at the top of the stack right after line 35?
cx
8- Suppose the offset of line 61 is 00000080 and the offset of line 28 is 00000040, after the call instruction in line 27 what offset is ESP holding? What about EIP?
ESP: 00000036 EIP: 00000080
9- After the execution of line 69 what happens to the offsets in ESP and EIP?
ESP+=4 pop EIP and point to line 28
10- What is the purpose of lines 36 and 37?
Assign dl to ax (numerical value)
11-How does the assembler know where the start of the program is?
The assembler finds the Main PROC to determine the start of the program
这里我已经把问题答案都写出来了,那么我们结合一下答案去看一下,都有哪些知识点叭!
首先第一问,include的目的是什么?
我们都知道,在写代码的时候,需要在前面加上各种include,那这个目的是什么呢?include是一个宏指令,旨在为了把头文件或者说某个库引入至源文件中,也就是我要用它;
第二问,.code
.data .code 这都是代表着数据段,代码段的开始,然后对于那些mian proc的话,有开始就要有结束,所以需要一个结束的end标志;
第三问,@data或者说data
@data是数据段的首地址,想要把那个送到ds也就是数据段中,那么就需要一个寄存器当做中间人;不允许直接把@data(立即数)送到ds的
第四问,GetDate
哇,这是个什么鬼啊,我在百度上没有查到,呜呜呜,但是我猜的是获取系统时间,那么问题又来了,获取的时间保存在哪了 ,分析之后,我感觉是保存在了cx dx里面,而且cx里面是年,dx里面是月日,所以后边时间是 月/日/年 这个也是美国的标准写法;
五六七略
第八问,关于call指令对于esp,eip的影响
我们都知道,对于一个好的程序来说,需要合理的子程序来辅助,使代码看着简洁明了,所以在汇编中,有一个call语句,那么这个call的原理是什么呢?压入的顺序又是什么?我们把子程序当成一个函数之后,就可以知道,call就是一个调用函数,这个函数可以是自定义的,可以是库中定义好的,然后一些函数会带有参数,那么这个时候就需要把参数从右到左的手动压入到堆栈中,(从右到左压入堆栈,pop的时候就是从左到右了),然后编译器会自动把eip压入到堆栈中,然后eip变化为需要跳转的地址,总之,call的时候,esp会-4,因为压入了eip,而ret的时候,会+4,pop了eip;
九十十一略
在题中见到的
EXTERN 是一个定义,声明 _GetDate 获取系统时间 _PutStr 输出字符串 _PutCh 输出单个字符 mov al, 0 ; Return code of 0 mov ah, 4ch ; Exit back to MSDOS int 21h 中断,然后退出 EQU 赋值 ,或者说命名 _PutCh 13, 10 ??换行? 没查到