这是一个运行在Linux下的、简单的汇编程序,使用NASM 2.11,展示了使用转义字符实现简单的“全屏”文本输出
; 可执行文件名 : eatterm; 版本 : 1.0; 创建日期 : 7/10/2016; 最后更新日期 : 7/10/2016; 作者 : Moonlight Poet; 描述 : 一个运行在Linux下的、简单的汇编程序,使用NASM 2.11,; 展示了使用转义字符实现简单的“全屏”文本输出; ; 使用以下命令生成:; nams -f elf -g -F stabs eatterm.asm; ld -o eatterm eatterm.o; SECTION .data ; 包含已初始化的数据SCRWIDTH: equ 80 ; 默认情况下我们假设80个字符宽PosTerm: db 27,"[01;01H" ;[ ; HPOSLEN: equ $-PosTerm ; 术语位置字符串的长度ClearTerm: db 27,"[2J" ; [2JCLEARLEN: equ $-ClearTerm ; 属于清除字符串的长度AdMsg: db "Eat at Joe's!" ; 广告消息ADLEN: equ $-AdMsg ; 广告消息的长度Prompt: db "Press Enter: " ; 用户提示信息PROMPTLEN: equ $-Prompt ; 用户提示信息的长度; 此表为我们提供了0到80之间的数字的以两位表示的ASCII位元(digit)。; 我们不是通过计算来产生插入终端控制字符串中的ASCII数字,; 而是在表中查找它们,一次取出两个ASCII位元到一个16位寄存器中,例如DX,; 然后将该寄存器的值防盗终端控制字符串PosTerm的适当位置。参见GoToXY。; 如果打算在更大的、超过80x80的控制台上工作,; 必须在Digits中添加额外的ASCII位元编码。; 注意:此处显示的代码只能工作在最大99*99的控制台上。Digits: db "0001020304050607080910111213141516171819" db "2021222324252627282930313233343536373839" db "4041424344454647484950515253545556575859" db "6061626364656667686970717273747576777879"SECTION .bss ; 包含未初始化的数据SECTION .text ; 包含代码的段;----------------------------------------------------------------------------------------------------; ClrScr: 清空Linux控制台; 最后更新日期: 7/10/2016; 输入参数: 无; 返回值: 无; 修改: 无; 调用: 内核sys_write; 描述: 发送预定以的控制字符串 [2J到控制台,它将清空整个显示器ClrScr: push rax ; 保存有关寄存器 push rbx push rcx push rdx mov ecx,ClearTerm ; 传递终端控制字符串的偏移地址 mov edx,CLEARLEN ; 传递终端控制字符串的长度 call WriteStr ; 发送终端控制字符串到控制台 pop rdx ; 恢复有关寄存器 pop rcx pop rbx pop rax ret;----------------------------------------------------------------------------------------------------; GotoXY: 将Linux控制光标定位到(X,Y)坐标处; 最后更新日期: 7/10/2016; 输入参数: X 存放到 AH,Y 存放到 AL; 返回值: 没有; 修改: PosTerm终端控制序列字符串; 调用: 内核sys_write; 描述: 为传递到AL和AH的X,Y坐标准备一个终端控制字符串; 并且调用sys_write将控制台光标定位到(X,Y)位置; 在调用GotoXY之后,写文本到控制台将从(X,Y)位置开始显示文本。GotoXY: push rbx ; 保存主调程序的寄存器 push rcx push rdx xor ebx,ebx ; 清零EBX xor ecx,ecx ; ECX寄存器操作同上; 插入Y的数字 mov bl,al ; 将Y的值放到缩放术语EBX寄存器中 mov cx,word [Digits+ebx*2] ; 取出十进制数字放到CX寄存器中 mov word [PosTerm+2],cx ; 将数字插入到控制字符串中; 插入X的数字 mov bl,ah ; 将X的值放到缩放术语EBX寄存器中 mov cx,word [Digits+ebx*2] ; 取出十进制数字放到CX寄存器中 mov word [PosTerm+5],cx ; 将数字插入控制字符串中; 发送控制序列到标准输出 mov ecx,PosTerm ; 传递控制字符串的地址 mov edx,POSLEN ; 传递控制字符串的长度 call WriteStr ; 发送控制字符串到控制台; 扫尾,返回: pop rdx pop rcx pop rax ret;----------------------------------------------------------------------------------------------------; WriteCtr: 发送一个字符串到一个80个字符串宽的Linux控制台的中央位置; 最后更新日期: 7/10/2016; 输入参数: 传递Y值到AL中,字符串地址到ECX中,字符串长度到EDX中; 返回值: 无; 修改: PosTerm终端控制序列字符串; 调用: GotoXY, WriteStr; 描述: 在一个80列宽的Linux控制台显示区域中央显示一个字符串; 为传入的字符串的长度计算X,; 然后调用GotoXY和WriteStr将该字符串发送到控制台WriteCtr: push rbx xor ebx,ebx mov bl,SCRWIDTH sub bl,dl shr bl,1 mov ah,bl call GotoXY call WriteStr pop rbx ret;----------------------------------------------------------------------------------------------------; WriteStr: 发送一个字符串到Linux控制台; 最后更新日期: 7/10/2016; 输入参数: 传递字符串地址到ECX中,字符串长度到EDX中; 返回值: 无; 修改: 无; 调用: 内核sys_write; 描述: 通过一个sys_write内核调用显示一个字符串到Linux控制台;WriteStr: push rax ; 保存相关的寄存器 push rbx mov eax,4 ; 指定sys_write调用 mov ebx,1 ; 指定文件描述符1:标准输出 int 80h ; 进行内核调用 pop rbx ; 恢复相关的寄存器 pop rax ret ; 返回 global _start ; 连接器需要这个来找到入口点_start: nop ; 这个无操作指令让gdb感到非常高兴 ; 首先我们清空终端显示器 call ClrScr mov al,12 mov ecx,AdMsg mov edx,ADLEN call WriteCtr mov ax,0117h call GotoXY mov ecx,Prompt mov edx,PROMPTLEN call WriteStr mov eax,3 mov ebx,0 int 80hExit: mov eax,1 mov ebx,0 int 80h
效果: