在16位汇编程序中,可以使用DOS中断21h
的功能号09h
来打印字符串;下面是一个简单的示例程序,演示了如何在16位汇编程序中打印字符串:
assume cs:code,ds:data
data segment
szBuffer db 0dh,0ah,'HelloWorld$' //定义字符串
data ends
code segment
start:
mov ax,data ; 将数据段地址加载到AX寄存器中
mov ds,ax ; 将AX中的数据段地址加载到DS寄存器中
(`DS` 寄存器是一个段寄存器,用于存储数据段的地址。)
mov dx,offset szBuffer ; 将szBuffer的偏移地址加载到DX寄存器中
mov ah,09h ; DOS功能号09h,用于显示字符串
int 21h ; 调用DOS中断21h
mov ax,4c00h
int 21h
code ends
end start
assume cs:code, ds:data
:指令告诉汇编器代码段位于 cs
寄存器所指示的代码段中,数据段位于 ds
寄存器所指示的数据段中。
data segment
和 data ends
之间的部分是数据段。在这里,szBuffer
被定义为一个字符串,以 $
结尾。
0dh
和 0ah
是 ASCII 字符集中的转义序列,分别代表回车(Carriage Return)和换行(Line Feed)。
-
0dh
对应于回车字符,表示将光标移动到当前行的开头,但不换行。通常与0ah
结合使用,表示回车换行,即在显示文本时,光标移到下一行的开头。 -
0ah
对应于换行字符,表示将光标移动到下一行的开头。
code segment
和 code ends
之间的部分是代码段。在 start
标签处开始执行。
mov ax, data
:将数据段地址加载到 AX
寄存器中。
mov ds, ax
:将 AX
中的数据段地址加载到 DS
寄存器中,这样程序就可以访问数据段中的数据。
mov dx, offset szBuffer
:将 szBuffer
的偏移地址加载到 DX
寄存器中;offset
操作符用于获取标签(如变量或标签)的偏移地址。
mov ah, 09h
:将 09h 存储在 AH
寄存器中,该值表示调用 DOS 中断 21h 的功能号 09h,用于显示字符串。
int 21h
:调用 DOS 中断 21h,显示字符串。
使用ML.exe对汇编程序进行处理后,执行处理后生成的exe程序,得到结果:
上述代码中我们使用OFFSET
操作符将szBuffer
字符串变量的地址偏移值计算出来,接着使用mov
指令将偏移值移入dx
寄存器中,接着使用DOS中断21h
的功能号09h
来打印字符串,即将功能号09h
传入ax
寄存器的高地址寄存器ah
中,最后使用int 21h
调用中断执行打印字符串的操作。
但其实在计算字符串的地址时除了使用OFFSET
操作符之外,我们还可以使用lea
指令取获取字符串的有效地址。
LEA指令
LEA指令(Load Effective Address)是x86汇编语言中的一条指令,用于将一个有效地址加载到寄存器中。它的主要用途是计算地址,但不进行内存访问。
语法
LEA destination, source
-
destination
是一个寄存器,用于存储计算出的地址。 -
source
是一个内存操作数,表示需要计算的有效地址。
此时我们使用lea
指令获取字符串的有效地址,并调用中断将其打印
assume cs:code,ds:data
data segment
szBuffer db 0dh,0ah,'HelloWorld$'
data ends
code segment
start:
mov ax,data
mov ds,ax
//打印字符串
mov ah,09h
lea dx,szbuffer
int 21h
int 21h ;再次调用中断打印字符串
mov ax,4c00h
int 21h
code ends
end start
-
lea dx, szBuffer
:将szBuffer
的偏移地址加载到DX
寄存器。 -
int 21h
:调用DOS中断21h,打印以$
结束的字符串。 -
int 21h
:再次调用中断,重复打印字符串。
最后运行该程序生成的exe
文件: