32位汇编语言学习笔记(25)--xlat指令

xlat指令用于从内存的转换表读入一个字节更新al寄存器的内容。在指令执行前,要求al寄存器保存转换表的索引值,ebx寄存器保存转换表的起始地址。

Assembly Language step by step programming with linux》第9章有一个使用这个指令的示例程序,此程序仍然用于把小写字母转换成大写字母:

SECTION .data   ; Section containing initialised data
 
 StatMsg: db "Processing...",10
 StatLen: equ $-StatMsg
 DoneMsg: db "...done!",10
 DoneLen: equ $-DoneMsg
 
; The following translation table translates all lowercase characters to
; uppercase. It also translates all non-printable characters to spaces,
; except for LF and HT.
 UpCase:
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,09h,0Ah,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh
 db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh
 db 40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh
 db 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh
 db 60h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh
 db 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,7Bh,7Ch,7Dh,7Eh,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h
 db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h

SECTION .bss   ; Section containing uninitialized data

 READLEN     equ 1024  ; Length of buffer
 ReadBuffer: resb READLEN ; Text buffer itself
 
SECTION .text   ; Section containing code

global  _start   ; Linker needs this to find the entry point!
 
_start:
 nop   ; This no-op keeps gdb happy...

; Display the "Processing..." message via stderr:
 mov eax,4  ; Specify sys_write call
 mov ebx,2  ; Specify File Descriptor 2: Standard error
 mov ecx,StatMsg  ; Pass offset of the message
 mov edx,StatLen  ; Pass the length of the message
 int 80h   ; Make kernel call

; Read a buffer full of text from stdin:
read:
 mov eax,3  ; Specify sys_read call
 mov ebx,0  ; Specify File Descriptor 0: Standard Input
 mov ecx,ReadBuffer ; Pass offset of the buffer to read to
 mov edx,READLEN  ; Pass number of bytes to read at one pass
 int 80h
 mov ebp,eax  ; Copy sys_read return value for safekeeping
 cmp eax,0  ; If eax=0, sys_read reached EOF
 jle done  ; Jump If equal or below (to 0, from compare)

; Set up the registers for the translate step:
 mov ebx,UpCase  ; Place the offset of the table into ebx
 mov edx,ReadBuffer ; Place the offset of the buffer into edx
 mov ecx,ebp  ; Place the number of bytes in the buffer into ecx

; Use the xlat instruction to translate the data in the buffer:
translate:
 mov al,byte [edx+ecx-1] ; Load character into AL for translation
 xlat   ; Translate character in AL via table
 mov byte [edx+ecx-1],al ; Put the translated character back in the buffer
 dec ecx   ; Decrement character count
 jnz translate  ; If there are more chars in the buffer, repeat

; Write the buffer full of translated text to stdout:
write:
 mov eax,4  ; Specify sys_write call
 mov ebx,1  ; Specify File Descriptor 1: Standard output
 mov ecx,ReadBuffer ; Pass offset of the buffer
 mov edx,ebp  ; Pass the # of bytes of data in the buffer
 int 80h   ; Make kernel call
 jmp read  ; Loop back and load another buffer full

; Display the "...done!" message via stderr:
done: 
 mov eax,4  ; Specify sys_write call
 mov ebx,2  ; Specify File Descriptor 2: Standard error
 mov ecx,DoneMsg  ; Pass offset of the message
 mov edx,DoneLen  ; Pass the length of the message
 int 80h   ; Make kernel call

; All done! Let's end this party:
 mov eax,1  ; Code for Exit Syscall
 mov ebx,0  ; Return a code of zero 
 int 80H   ; Make kernel call                          

程序分析:

UpCase是一个字节数组,此数组用于把小写字母转换成大写字母。

mov ebx, UpCase //ebx=UpCaseebx保存转换表的起始地址

mov edx, ReadBuffer //edx=ReadBufferedx保存读入缓存的起始地址

mov ecx, ebp //ecx=读入缓存的字节数,ecx用于循环计数

translate:

        mov al, byte [edx+ecx-1] //al=edx[ecx-1]al保存的是输入字符的ASCII值,从最后一个输入字符开始转换。

        xlat                    //指令执行结果,是al= UpCase[al]

        mov byte [edx+ecx-1], al //放回转换的这个字节到edx[ecx-1]

        dec ecx                      //ecx1

        jnz translate             //如果ecx不等于0,跳转到translate继续循环。

makefile文件如下:

xlat1: xlat1.o

        ld-o xlat1 xlat1.o

xlat1.o: xlat1.asm

        nasm-f elf -g -F stabs xlat1.asm

测试:

[root@bogon xlat1]# make
nasm -f elf -g -F stabs xlat1.asm
ld -o xlat1 xlat1.o
[root@bogon xlat1]# ./xlat1
Processing...
a
A
abc
ABC
...done!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值