2021.09.24 00:44:10
[[Assembly|汇编笔记系列]]
先上例程。
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码的二进制的某一位不同。使用and
和or
就可以不使用判断语句而直接转换大小写了。
call [标号]
会将CS:IP
中的IP的地址设置为指向标号所在的位置,同时将当前的CS:IP中的IP压入栈中。相当于这样:push IP
jmp [标号和当前行的相对距离]
是不是很像C语言的goto呢?
pop IP
。二者组合使用,就可以实现子程序的机制。其框架如下:
标号:
指令
ret
使用子程序的框架如下:
assume cs:code
code segment
main: :
:
call sub1
:
:
mov ax,4c00h
int 21h
sub1: :
:
call sub2
:
:
ret
sub2: :
:
:
ret
code ends
end main
有几种思路。
第一种,利用寄存器传递参数。仅适用于参数个数少的情况。
第二种,用寄存器传递参数长度,给子程序传递参数地址。
第三种,利用栈来传递参数。
有可能在主程序和子程序中,都有同样的寄存器被使用(比如循环计数寄存器CX)。此时,程序就不会按照预期来运行。
我们的解决方法是,在子程序中使用寄存器时,将所有值存储到栈里,在子程序返回前再恢复。
在实验中提到了三个子程序,分别是字符串显示,解决除法溢出,数值显示。后面我会试着自己写出来。