32位汇编语言学习笔记(35)--显示ASCII表
来源:互联网 发布:敏感端口 编辑:程序博客网 时间:2024/06/06 22:18
这个程序出自《Assembly Language step by step programming with linux》第11章,首先需要先介绍几条指令:
jcxz label,当cx寄存器等于0时,跳转。
jecxz label,当ecx寄存器等于0时,跳转。
loopnz label,ecx=ecx-1,当ecx寄存器不等于0时并且ZF标志位未被设置时跳转,如果ecx寄存器等于0,或者ZF标志位已经被设置,就结束循环了。
loopne label,与loopnz相同。
接下来看程序:
SECTION .data; Section containing initialised dataEOL equ 10; Linux end-of-line characterFILLCHRequ 32; Default to ASCII space characterCHRTROWequ 2; Chart begins 2 lines from topCHRTLENequ 32; Each chart line shows 32 chars; This escape sequence will clear the console terminal and place the; text cursor to the origin (1,1) on virtually all Linux consoles:ClrHome db 27,"[2J",27,"[01;01H"CLRLENequ $-ClrHome; Length of term clear stringSECTION .bss; Section containing uninitialized dataCOLSequ 81; Line length + 1 char for EOLROWSequ 25; Number of lines in displayVidBuffresb COLS*ROWS; Buffer size adapts to ROWS & COLSSECTION .text; Section containing codeglobal _start; Linker needs this to find the entry point!; This macro clears the Linux console terminal and sets the cursor position; to 1,1, using a single predefined escape sequence.%macroClearTerminal 0pushad; Save all registersmov eax,4; Specify sys_write callmov ebx,1; Specify File Descriptor 1: Standard Outputmov ecx,ClrHome; Pass offset of the error messagemov edx,CLRLEN; Pass the length of the messageint 80H; Make kernel callpopad; Restore all registers%endmacroShow:pushad; Save all registersmov eax,4; Specify sys_write callmov ebx,1; Specify File Descriptor 1: Standard Outputmov ecx,VidBuff; Pass offset of the buffermov edx,COLS*ROWS; Pass the length of the bufferint 80H; Make kernel callpopad; Restore all registersret; And go home!ClrVid:push eax; Save caller's registerspush ecxpush edicld; Clear DF; we're counting up-memorymov al,FILLCHR; Put the buffer filler char in ALmov edi,VidBuff; Point destination index at buffermov ecx,COLS*ROWS; Put count of chars stored into ECXrep stosb; Blast chars at the buffer; Buffer is cleared; now we need to re-insert the EOL char after each line:mov edi,VidBuff; Point destination at buffer againdec edi; Start EOL position count at VidBuff char 0mov ecx,ROWS; Put number of rows in count registerPtEOL:add edi,COLS; Add column count to EDUmov byte [edi],EOL; Store EOL char at end of rowloop PtEOL; Loop back if still more linespop edi; Restore caller's registerspop ecxpop eaxret; and go home!Ruler: push eax; Save the registers we changepush ebxpush ecxpush edimov edi,VidBuff; Load video address to EDIdec eax; Adjust Y value down by 1 for address calculationdec ebx; Adjust X value down by 1 for address calculationmov ah,COLS; Move screen width to AHmul ah; Do 8-bit multiply AL*AH to AXadd edi,eax; Add Y offset into vidbuff to EDIadd edi,ebx; Add X offset into vidbuf to EDI; EDI now contains the memory address in the buffer where the ruler; is to begin. Now we display the ruler, starting at that position: mov al,'1'; Start ruler with digit '1'DoChar: stosb; Note that there's no REP prefix!add al,'1'; Bump the character value in AL up by 1 aaa; Adjust AX to make this a BCD additionadd al,'0'; Make sure we have binary 3 in AL's high nybble loop DoChar; Go back & do another char until ECX goes to 0pop edi; Restore the registers we changedpop ecxpop ebxpop eaxret; And go home!;-------------------------------------------------------------------------; MAIN PROGRAM:_start:nop; This no-op keeps gdb happy...; Get the console and text display text buffer ready to go:ClearTerminal; Send terminal clear string to consolecall ClrVid; Init/clear the video buffermov eax,1; Start ruler at display position 1,1mov ebx,1mov ecx,32; Make ruler 32 characters widecall Ruler; Generate the ruler; Now let's generate the chart itself:mov edi,VidBuff; Start with buffer address in EDIadd edi,COLS*CHRTROW; Begin table display down CHRTROW linesmov ecx,224; Show 256 chars minus first 32mov al,32; Start with char 32; others won't show.DoLn:mov bl,CHRTLEN; Each line will consist of 32 chars.DoChr:jcxz AllDone; When the full set is printed, quitstosb; Note that there's no REP prefix!inc al; Bump the character value in AL up by 1dec bl; Decrement the line counter by oneloopnz .DoChr; Go back & do another char until BL goes to 0add edi,COLS-CHRTLEN; Move EDI to start of next linejmp .DoLn; Start display of the next line; Having written all that to the buffer, send the buffer to the console:AllDone:call Show; Refresh the buffer to the consoleExit:mov eax,1; Code for Exit Syscallmov ebx,0; Return a code of zeroint 80H; Make kernel call
程序分析:
mov eax,1 //设置标尺的起始坐标1,1
mov ebx,1
mov ecx,32 //标尺的宽度是32个字节
call Ruler //把标尺写入缓存
mov edi,VidBuff //edi= VidBuff
add edi,COLS*CHRTROW //edi= VidBuff+ COLS*2
mov ecx,224 //总循环次数是224=256-32
mov al,32 //al=32,第一个打印的ASCII码字符
.DoLn: mov bl,CHRTLEN //bl=32,每行打印的字符数
.DoChr: jcxz AllDone //cx=0跳转到AllDone,结束外层循环。
stosb //填充al值到edi指向的内存。
inc al //al=al+1
dec bl //bl=bl-1
loopnz .DoChr //当bl值等于0时,会设置ZF标志位,所以会结束循环,因此,每32次循环后,结束一次内层循环。
add edi,COLS-CHRTLEN //edi切换到下一行的起始位置
jmp .DoLn //进行下一个外层循环,写入下一行ASCII码值。
AllDone:
call Show //显示ASCII码表
makefile文件内容:
showchar: showchar.old -o showchar showchar.oshowchar.o: showchar.asmnasm -f elf -g -F stabs showchar.asm
测试:
[root@bogon showchar]# makenasm -f elf -g -F stabs showchar.asmld -o showchar showchar.o[root@bogon showchar]# ./showchar12345678901234567890123456789012 !"#$%&'()*+,-./0123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ `abcdefghijklmnopqrstuvwxyz{|}~ ������������������������������ �������������������������������� �������������������������������� ��������������������������������
- 32位汇编语言学习笔记(35)--显示ASCII表
- 32位汇编语言学习笔记(37)--显示命令行参数
- 32位汇编语言学习笔记(38)--显示命令行参数(2)
- 32位汇编语言学习笔记(39)--显示环境变量
- 32位汇编语言学习笔记(44)--显示命令行参数(3)
- windows下32位汇编语言学习笔记
- windows下32位汇编语言学习笔记
- windows下32位汇编语言学习笔记
- 32位汇编语言学习笔记(18)--联合
- 32位汇编语言学习笔记(34)--一个数据的柱状图显示程序
- 32位汇编语言学习笔记(32)--loop指令
- 32位汇编语言学习笔记(1)--简单示例
- 32位汇编语言学习笔记(2)--数据传送指令
- 32位汇编语言学习笔记(4)--移位操作
- 32位汇编语言学习笔记(5)--特殊的算术操作
- 32位汇编语言学习笔记(6)--设置条件码
- 32位汇编语言学习笔记(7)--跳转指令
- 32位汇编语言学习笔记(11)--条件传送指令
- Chromium源码获取与编译--附加一个简单例子的编译
- 【BZOJ2460】【Beijing2011】元素 线性基
- ECshop2.7.3彻底去版权(Powered by ECShop)
- 指针与取地址符&
- [leetcode] 126 Word Ladder ii bfs dfs
- 32位汇编语言学习笔记(35)--显示ASCII表
- ios 手机验证码随机出现六位数的方法(二)
- 【UNIX】内核对进程的调度机制
- struts2 jsp 中 用<s:url>赋值多个参数 用<a>时传第二个参数就多出了amp; 而用<s:a >则不会 求解! 求解! 求解!
- 新浪微博数据挖掘食谱之十四: 用户篇 (分析用户的粉丝和朋友)
- 将心比心,你的人生道路才会更宽广
- 【UNIX】内核对内核空间内存的管理以及对用户进程的堆内存分布
- NSDate比较
- IOS 开发学习一 基础知识