❤️💕💕汇编语言目前仍在发挥着不可替代的作用,在效率上无可替代,在底层,学习linux内核,计算机外围设备和驱动,都离不开汇编。Myblog:http://nsddd.top
[TOC]
- 一个执行文件
.exe
在双击执行时,首先由操作系统分析本程序的段占用情况- 包括多少段、各段长度、代码段第一条指令的偏移
- 然后在当前内存中寻找合适区域,并分配CS、DS、SS、ES等各段
- 把
.exe
执行文件中的数据调入内存DS
段,代码调入内存CS
段…….. - 然后把CPU的CS变为当前分配的代码段值,IP为第一条指令的偏移,从而开始程序的执行
SP
为堆栈段大小(即最大值-wB)
- 在汇编程序时,通过交叉文件可以看出各段大小。
汇编语言也是支持模块化程序设计,并非高级语言才可以。
assume cs:code
code segment
main: ...
call sub1 ;调用子程序sub1
...
mov ax, 4c00h
int 21h
sub1: ... ;子程序sub1开始
call sub2 ;调用子程序sub1
...
ret ;子程序返回
sub2: ... ;子程序sub2开始
...
ret ;子程序返回
code ends
end main
;计算data段中第一组数据的 3 次方,结果保存在后面一组dword单元中。
assume cs:code
data segment
dw 1,2,3,4,5,6,7,8
dd 0,0,0,0,0,0,0,0
data ends
code segment
start:mov ax,data
mov ds,ax
mov si,0 ;ds:si指向第一组word单元 dw
mov di,16 ;ds:di指向第二组dword单元 dd
mov cx,8 ;循环处理
s:mov bx,[si]
call cube ;调用cube
mov [di],ax ;低十六位置
mov [di].2,dx ;高十六位
add si,2 ;ds:si指向下一个word单元
add di,4 ;ds:di指向下一个dword单元
loop s
mov ax,4c00h
int 21h
cube:mov ax,bx ;求出bx的三次方,然后返回
mul bx
mul bx
ret
code ends
end start
依次的进行编译链接执行,我们在后面
-g
看到后面的结果。我们发现的问题,如果需要传递的数据有很多,寄存器不够了怎么办。可以用内存单元批量传递数据。
;将data段中的字符串转化为大写
assume cs:code
data segment
db 'conversation'
data ends
code segment
start: mov ax,data
mov ds,ax
mov si,0
mov cx,12
call capital
mov ax,4c00h
int 21h
capital: and byte ptr [si],11011111b ;si的字节依次转化为大写
inc si
loop capital
ret
code ends
end start
原理:由调用者将需要传递给子程序的参数压入栈中、子程序从栈中取得参数
;设 a = 3 、b = 1 ,计算:( a – b ) ^ 3 , a、b为word类型数据
assume cs:code
code segment
start: mov ax , 1
push ax
mov ax , 3
push ax ;注意参数压栈的顺序
call difcube ;这个时候 把下一个IP压入栈,栈顶依旧走了一步 调用子程序
mov ax,4c00h
int 21h
difcube :
push bp ;bp基址指针寄存器,用于堆栈段寻址
;很重要的一点:子程序要用dp,我们为了避免丢失有用数据。先入栈,返回前出栈
mov bp , sp
mov ax , [ bp + 4 ] ; 将栈中a的值送入ax 中
sub ax , [ bp + 6 ] ; 减栈中b的值
mov bp , ax
mul bp
mul bp
pop bp ;bp可能在使用的时候主程序在用,所以我们可以用pop保证出去后不影响主程序的使用;恢复保存bp的值
ret 4 ;ret ip出栈,转移到后面执行
code ends
end start
指令
ret n
的含义 把栈后面的四个字节忽略掉,直接转移到后面去:pop ip add sp, n