SECTION .bss ; Section containing uninitialized data
BUFFLEN equ 16 ;We read the file 16 bytes at a time
Buff: resb BUFFLEN ; Text buffer itself
SECTION .data ; Section containing initialised data
HexStr: db " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",10
HEXLEN equ $-HexStr
Digits: db "0123456789ABCDEF"
SECTION .text ; Section containing code
global _start ; Linker needs this tofind the entry point!
_start:
nop ; This no-op keeps gdbhappy...
; Read a buffer full of text from stdin:
Read:
mov eax,3 ; Specify sys_readcall
mov ebx,0 ; Specify File Descriptor 0: Standard Input
mov ecx,Buff ; Pass offset of the buffer to read to
mov edx,BUFFLEN ; Pass number ofbytes to read at one pass
int 80h ; Call sys_readto fill the buffer
mov ebp,eax ; Save # of bytes read from file for later
cmp eax,0 ; If eax=0,sys_read reached EOF on stdin
jle Done ; Jump If equal or below(to 0, from compare)
;Set up the registers for the process buffer step:
mov esi,Buff ; Place address of file buffer into esi
mov edi,HexStr ; Place address of line string into edi
xor ecx,ecx ; Clear line string pointer to 0
;Go through the buffer and convert binary values to hex digits:
Scan:
xor eax,eax ; Clear eax to 0
;Here we calculate the offset into the line string, which is ecx X 3
mov edx,ecx ; Copy the pointer into line string into edx
lea edx,[edx*2+edx]
;Get a character from the buffer and put it in both eax and ebx:
mov al,byte [esi+ecx] ; Put a byte from the input buffer intoal
mov ebx,eax ; Duplicate the byte in bl for second nybble
;Look up low nybble character and insert it into the string:
and al,0Fh ; Mask outall but the low nybble
mov al,byte [Digits+eax] ; Look up the char equivalent of nybble
mov byte [HexStr+edx+2],al ; Write the char equivalent to line string
;Look up high nybble character and insert it into the string:
shr bl,4 ; Shift high 4 bits of char into low 4 bits
mov bl,byte [Digits+ebx] ; Look up charequivalent of nybble
mov byte [HexStr+edx+1],bl ; Write thechar equivalent to line string
;Bump the buffer pointer to the next character and see if we're done:
inc ecx ;Increment line string pointer
cmp ecx,ebp ; Compare to the number of characters in the buffer
jna Scan ; Loop back if ecx is <= number of chars in buffer
; Write the line of hexadecimal values tostdout:
mov eax,4 ; Specify sys_writecall
mov ebx,1 ; Specify FileDescriptor 1: Standard output
mov ecx,HexStr ; Pass offsetof line string
lea edx,[ebp*2+ebp]; Pass size of the line string
int 80h ; Make kernelcall to display line string
jmp Read ; Loop back and load filebuffer again
; All done! Let's end this party:
Done:
mov eax,1 ; Code for ExitSyscall
mov ebx,0 ; Return a code ofzero
int 80H ; Make kernelcall
这个程序在3个系统调用上的代码与前面大小写转换程序的代码类似,下面主要分析新增部分的代码,这部分代码用于把输入字符转换成16进制数输出:
mov esi,Buff //esi = Buff
mov edi,HexStr //edi=HexStr
xor ecx,ecx //对ecx清零。
Scan:
xor eax,eax //对eax清零。
mov edx,ecx //edx = ecx,ecx从0开始,用于循环计数。
lea edx,[edx*2+edx] //edx = 3*edx = 3*ecx
mov al,byte [esi+ecx] //al = Buf[ecx]
mov ebx,eax //ebx = eax,这样bl=al
and al,0Fh //al与0x0F进行与运算,清除高4位,保留低4位。
mov al,byte [Digits+eax] //al = Digits[eax]
mov byte [HexStr+edx+2],al //HexStr[3*ecx+2]= al
shr bl,4 //逻辑右移4位,左边空出的位填0,这样bl的低4位就是原来高4位的值。
mov bl,byte [Digits+ebx] //bl = Digits[ebx]
mov byte [HexStr+edx+1],bl //HexStr[3*ecx +1]= bl
inc ecx //ecx自增
cmp ecx,ebp //比较ecx和ebp(读入Buf的字节个数)
jna Scan //如果ecx小于等于ebp,跳转到Scan,继续循环。
makefile文件:
hexdump1: hexdump1.o
ld -m elf_i386 -o hexdump1 hexdump1.o
hexdump1.o: hexdump1.asm
nasm -f elf32 -g -F stabs hexdump1.asm -l hexdump1.lst
测试:
[root@bogon hexdump1]# ./hexdump1
abcde
6162 63 64 65 0A