汇编学习笔记:转移指令与子程序

[[Assembly|汇编笔记系列]]

例程

先上例程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
inc si
loop capital
ret
code ends
end start

这个程序的作用,是将data段中的字符串转化为大写。转换的原理,是大小写字母的ASCLL码的二进制的某一位不同。使用andor就可以不使用判断语句而直接转换大小写了。

简介

  • call:用来进行标号跳转。call [标号]会将CS:IP中的IP的地址设置为指向标号所在的位置,同时将当前的CS:IP中的IP压入栈中。相当于这样:
1
2
push IP
jmp [标号和当前行的相对距离]

是不是很像C语言的goto呢?

  • ret:用来返回程序之前的位置。ret就相当于pop IP

二者组合使用,就可以实现子程序的机制。其框架如下:

1
2
3
标号:
指令
ret

使用子程序的框架如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
assume cs:code
code segment
main: :
:
call sub1
:
:
mov ax,4c00h
int 21h

sub1: :
:
call sub2
:
:
ret

sub2: :
:
:
ret
code ends
end main

参数传递

有几种思路。

第一种,利用寄存器传递参数。仅适用于参数个数少的情况。

第二种,用寄存器传递参数长度,给子程序传递参数地址。

第三种,利用栈来传递参数。

寄存器冲突

有可能在主程序和子程序中,都有同样的寄存器被使用(比如循环计数寄存器CX)。此时,程序就不会按照预期来运行。

我们的解决方法是,在子程序中使用寄存器时,将所有值存储到栈里,在子程序返回前再恢复。

三个子程序

在实验中提到了三个子程序,分别是字符串显示,解决除法溢出,数值显示。后面我会试着自己写出来。

作者

xeonds

发布于

2021-09-24

更新于

2024-11-07

许可协议

评论