Hi everyone!
I'm new to x86 assembly programming. So far I learn some basic skills from the textbook, "Assembly Language For Intel-Based Computers", 4th edition. I read up to chapter 5 about the link library provided by the book. For every program I made was using the book's include directive, "INCLUDE Irvine32.inc". Recently I need to display a table with decimal and hexadecimal number conversion. So, in this program, I used the "WriteDec" and "WriteHex" procedures from the link library to shows the hex number. However, I just need to show the number ranging from 0-255. To show the number, I need to put the number into EAX register and CALL WriteHex.
For example,
MOV EAX, 48
CALL WriteHex
The result showing is "00000030" in hex, but i just want the lower 8 bits in EAX, which is "30".
Q: So, what should I do to extract 8-bit "30" from 32-bit "00000030" and print it to the standard output? (I cannot use WriteHex since it will show the entire 32bit only)
p.s.Is there a different way to display values in a specific register without using the procedures from the link library, e.g. WriteHex, WriteString, etc?
I'm using both VS 2005 and MASM32 assembler.
You could try taking a look at the source for the WriteHex procedure in Irvine32.asm. From that you should be able to create your own procedure (with a different name) that will display only 2 digits, as well as learn one method of converting a value in a register to a hex string.
Or checkout the bitwise operations, like AND, if you really want to keep the last 8 bit-digits only ... and still use a 32-bit register.
I think he is more interested in editing the output to the last two characters than in restricting the register value.
Dave.
Quote from: BlackVortex on November 06, 2008, 07:18:53 PM
Or checkout the bitwise operations, like AND, if you really want to keep the last 8 bit-digits only ... and still use a 32-bit register.
The numbers will be contained entirely in the last 8 bits. The problem is the leading zeros in the string.
Daniellam, you could try tinkering with this code snippet:
http://www.masm32.com/board/index.php?topic=9062.msg65629#msg65629
The "TextToHex" proc calls the "b2hex" proc for each byte needing conversion. Experiment. :U
Or check out http://www.masm32.com/board/index.php?topic=4475.0 or http://www.masm32.com/board/index.php?topic=7741.0 ... search for "convert hex" for even more.
Hi daniellam:
try this:
; BINIHEX.ASM Saturday, November 08, 2008 6:22 PM
; by herge
include \masm32\include\masm32rt.inc
.data
sOut db 20 dup (0)
db 0
CrLf db 13, 10 ,0
.code
rotate proc
; esi > String Output(Print Buffer)
; ch number of digits
; cl number of bits
rol bx,cl ; left digit to right digit
mov al,bl ; move to AL
and al,0Fh; mask off left digit
;From 8080a/8085 assembly language
;programming pg 7-3
; Lance A. Leventhal
; Binary digit to Ascii Digit
; with no jumps
add al,90h ; add BCD 90
daa ; decimal adjust
adc al,40h ; add BCD 40 and carry
daa ; decimal adjust
mov byte ptr [esi] , al
inc esi ; > next digit
dec ch ; done 4 digits
jnz rotate ; yet
ret
rotate endp
BINIHEX proc
;
; subroutine to convert biniary number in BX
; to HEX on console screen
; esi > Output String
push eax
push ecx
push edx
mov cx,0404h
; ch number of digits
; cl number of bits
call rotate
pop edx
pop ecx
pop eax
ret
BINIHEX endp
DUMP_BYTE proc
; Dump BH to Buffer
; esi > Output String
; uses BINIHEX logic
push eax
push ecx
push edx
mov cx, 0204h
call rotate
pop edx
pop ecx
pop eax
ret
DUMP_BYTE endp
DUMP_WORD proc
; Dump word BX to screen
; Print 'H' after Hex digits
; esi > Output String
pushf
push eax
push ecx
push edx
call BINIHEX
mov al,'H'
mov byte ptr [esi] , al
inc esi
mov al, 0
mov byte ptr [esi] , al
inc esi
pop edx
pop ecx
pop eax
popf
ret
DUMP_WORD endp
Start:
lea esi, sOut
mov bh, 255 ; Note BH NOT BL!!!
call DUMP_BYTE
lea esi, sOut
invoke StdOut, esi
getkey
invoke StdOut, offset CrLf
mov bx, 01234h
mov esi, offset sOut
call DUMP_WORD
lea esi, sOut
invoke StdOut, esi
invoke StdOut, offset CrLf
inkey
exit
end Start
Regards herge
herge,
I was playing around with your code, and I came up with a procedure, dwtoh, that is derived from the code you posted. It works fine but, on my system, its three times slower than the dw2hex procedure in the masm32 library. It was fun writing it though. [edit] And maybe danielm can use btoh.
INCLUDE \masm32\include\masm32rt.inc
INCLUDE Timers.asm
.DATA
ALIGN 4
bVal BYTE 12h
ALIGN 4
wVal WORD 1234h
ALIGN 4
dwVal DWORD 12345678h
ALIGN 4
szOut BYTE 32 DUP(0)
szCrLf BYTE 13, 10 ,0
.CODE
;----------------------------------------
btoh PROC pB:PTR BYTE, pszBuffer:PTR BYTE
mov ecx, pszBuffer
mov eax, pB
;xor edx, edx ; not really necessary
mov dh, BYTE PTR [eax]
REPEAT 2
rol dx, 4
mov al, dl ; move to AL
and al, 0Fh ; mask off left digit
add al, 90h ; add BCD 90
daa ; decimal adjust
adc al, 40h ; add BCD 40 and carry
daa ; decimal adjust
mov BYTE PTR [ecx], al
inc ecx ; > next digit
ENDM
mov BYTE PTR [ecx], 0
ret
btoh ENDP
;----------------------------------------
wtoh PROC pW:PTR WORD, pszBuffer:PTR BYTE
mov ecx, pszBuffer
mov eax, pW
;xor edx, edx ; not really necessary
mov dx, WORD PTR [eax]
REPEAT 4
rol dx, 4
mov al, dl ; move to AL
and al, 0Fh ; mask off left digit
add al, 90h ; add BCD 90
daa ; decimal adjust
adc al, 40h ; add BCD 40 and carry
daa ; decimal adjust
mov BYTE PTR [ecx], al
inc ecx ; > next digit
ENDM
mov BYTE PTR [ecx], 0
ret
wtoh ENDP
;----------------------------------------
dwtoh PROC pD:PTR DWORD, pszBuffer:PTR BYTE
mov ecx, pszBuffer
mov eax, pD
mov edx, DWORD PTR [eax]
REPEAT 8
rol edx, 4
mov al, dl ; move to AL
and al, 0Fh ; mask off left digit
add al, 90h ; add BCD 90
daa ; decimal adjust
adc al, 40h ; add BCD 40 and carry
daa ; decimal adjust
mov BYTE PTR [ecx], al
inc ecx ; > next digit
ENDM
mov BYTE PTR [ecx], 0
ret
dwtoh ENDP
;----------------------------------------
Start:
INVOKE btoh, ADDR bVal, ADDR szOut
INVOKE StdOut, ADDR szOut
INVOKE StdOut, ADDR szCrLf
INVOKE wtoh, ADDR wVal, ADDR szOut
INVOKE StdOut, ADDR szOut
INVOKE StdOut, ADDR szCrLf
INVOKE StdOut, ADDR szCrLf
timer_begin 100000, HIGH_PRIORITY_CLASS
INVOKE dwtoh, ADDR dwVal, ADDR szOut
timer_end
push eax
INVOKE StdOut, SADD("dwtoh = ")
pop eax
INVOKE StdOut, udword$(eax)
INVOKE StdOut, ADDR szCrLf
INVOKE StdOut, ADDR szOut
INVOKE StdOut, ADDR szCrLf
INVOKE StdOut, ADDR szCrLf
timer_begin 100000, HIGH_PRIORITY_CLASS
INVOKE dw2hex, dwVal, ADDR szOut
timer_end
push eax
INVOKE StdOut, SADD("dw2hex = ")
pop eax
INVOKE StdOut, udword$(eax)
INVOKE StdOut, ADDR szCrLf
INVOKE StdOut, ADDR szOut
INVOKE StdOut, ADDR szCrLf
inkey SADD(13,10,"Press any key to exit ... ")
exit
END Start
Coders just want to have fun...
reinventing the wheels ?
Dont reinvent at the wheels,
instead where it meets the road...
at the tires, ie, in this case, the output ?
Just a thought.
Hi All:
We are forgetting the easiest solution why not start in the
miidle of the print buffer. It's very unlikely this position
is going to move.
Either hard code it or search for a byte greater than
Ascii Zero and before the ending NULL(Zero Byte).
Regards herge
Hi All:
using dw2hex from c:\masm32\m32lib\dw2hex.asm
; ########################################################################
;
; This original module was written by f0dder.
;
; Part of the code has been optimised by Alexander Yackubtchik
;
; ########################################################################
include \masm32\include\masm32rt.inc
.386
option casemap :none ; case sensitive
.data
HexIn dd 0
HexOut db 20 dup(0)
db 0
CrLf db 13, 10, 0
.code
; ########################################################################
dw2hex proc source:DWORD, lpBuffer:DWORD
push esi
mov edx, lpBuffer
mov esi, source
xor eax, eax
mov ecx, eax
mov [edx+8], al ; put terminator at correct length
mov cl, 7 ; length of hexstring - 1
@@:
mov eax, esi ; we're going to work on AL
and al, 00001111b ; mask out high nibble
cmp al, 10
sbb al, 69h
das
mov [edx + ecx], al ; store the asciihex(AL) in the string
shr esi, 4 ; next nibble
dec cl ; decrease counter (one byte less than dec cl :-)
jns @B ; eat them if there's any more
pop esi
ret
dw2hex endp
findNotZero proc uses ecx
mov ecx, 8
@@:
mov al, byte ptr [esi]
inc esi
cmp al, '0'
jnz @F
dec cl
jnz @B
@@:
dec esi
ret
findNotZero endp
; #########################################################################
Start:
mov eax, -1
mov ecx, 24
@@:
mov HexIn, eax
push eax
push ecx
invoke dw2hex, HexIn, addr HexOut
mov esi, offset HexOut
call findNotZero
invoke StdOut, esi
invoke StdOut, addr CrLf
pop ecx
pop eax
inc eax
dec ecx
jnz @B
inkey
exit
end Start
Regards herge