红联Linux门户
Linux帮助

汇编语言使用转义字符实现简单的“全屏”文本输出

发布时间:2016-07-11 15:40:16来源:linux网站作者:月光诗人
这是一个运行在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"; <ESC>[<Y>;<X>H
POSLEN: equ $-PosTerm; 术语位置字符串的长度
ClearTerm: db 27,"[2J"; <ESC>[2J
CLEARLEN: 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
; 描述:发送预定以的控制字符串<ESC>[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 80h
Exit:mov eax,1
mov ebx,0
int 80h
 
效果:
汇编语言使用转义字符实现简单的“全屏”文本输出
 
本文永久更新地址:http://www.linuxdiyf.com/linux/22285.html