flat assembler
Message board for the users of flat assembler.
Index
> Main > Printing the value of a register to the console |
Author |
|
FlierMate7 11 Oct 2023, 08:08
You'll need a int_to_hex conversion routine.
|
|||
11 Oct 2023, 08:08 |
|
SH4DOW4RE 11 Oct 2023, 08:19
FlierMate7 wrote: You'll need a int_to_hex conversion routine. How would I do that ? |
|||
11 Oct 2023, 08:19 |
|
FlierMate7 11 Oct 2023, 10:06
SH4DOW4RE wrote:
Hi. You can refer to example code by revolution: https://board.flatassembler.net/topic.php?t=23007 In "print_hex16" routine. |
|||
11 Oct 2023, 10:06 |
|
revolution 11 Oct 2023, 10:36
To remove the requirement for clicking a new link I repost the short and inefficient code here.
Code: STDOUT_FILENO = 1 SYS64_write = 1 hex_table: db '0123456789abcdef' print_hex16: ;rax = value push rbx rax rcx rdx mov ecx,16 lea rbx,[hex_table] .next_nibble: rol rax,4 mov edx,eax and edx,0xf mov dl,[rbx + rdx] call print_char dec ecx jnz .next_nibble pop rdx rcx rax rbx ret print_char: ;dl = character push rsi rdi rax rcx r11 rdx mov rsi,rsp mov edx,1 mov eax,SYS64_write mov edi,STDOUT_FILENO syscall pop rdx r11 rcx rax rdi rsi ret |
|||
11 Oct 2023, 10:36 |
|
revolution 11 Oct 2023, 17:22
I created an example that might be slightly more efficient and shows how to suppress or enable leading zeros at assembly time.
Code: format elf64 executable STDOUT_FILENO = 1 SYS64_write = 1 SYS64_exit_group = 231 segment readable writeable executable hex_table: db '0123456789abcdef' entry $ rdtscp push rax rdx rcx pop rax call print_hex16 mov dl,10 call print_char pop rdx rax shl rdx,32 or rax,rdx call print_hex16 mov dl,10 call print_char mov eax,SYS64_exit_group xor edi,edi syscall print_hex16: ;rax = value push rsi rbx rcx rdx lea rbx,[hex_table] mov edx,16 sub rsp,rdx .next_nibble: mov ecx,eax and ecx,0xf mov cl,[rbx + rcx] ; to enable/suppress leading zeros reverse the order of the next two instructions shr rax,4 dec edx ; to enable/suppress leading zeros reverse the order of the previous two instructions mov [rsp + rdx],cl jnz .next_nibble lea rsi,[rsp + rdx] sub edx,16 neg edx call print_string add rsp,16 pop rdx rcx rbx rsi ret print_string: ;rsi = string ;rdx = length push rdi rax rcx r11 mov eax,SYS64_write mov edi,STDOUT_FILENO syscall pop r11 rcx rax rdi ret print_char: ;dl = character push rsi rdi rax rcx r11 rdx mov eax,SYS64_write mov edi,STDOUT_FILENO mov rsi,rsp mov edx,1 syscall pop rdx r11 rcx rax rdi rsi ret |
|||
11 Oct 2023, 17:22 |
|
redsock 11 Oct 2023, 20:05
My example is also not terribly efficient but shows a slightly different way to achieve the same thing. Note that my example writes twice to the stack unnecessarily and wastes 7 bytes of stack space after the value and linefeed. Also, if the value to convert to hex is already zero, this unnecessarily writes a 0 instead of skipping the loop entirely
Code: format elf64 executable segment readable executable hexchars: db '0123456789abcdef' entry $ mov rax, 0x3030303030303030 ; all '0' mov ecx, 10 ; LF sub rsp, 16 ; stackspace for struct timeval mov rdi, rsp ; first argument for gettimeofday, struct timeval * push rcx ; space for output push rax ; space for output push rax ; space for output mov eax, 96 ; gettimeofday syscall xor esi, esi ; struct timezone * syscall mov edx, 15 ; offset into output to start at, just before the LF mov rax, [rsp+24] ; struct timeval's tv_sec mov rcx, [rsp+32] ; struct timeval's tv_usec mov rsi, rsp ; start of hexchar output and first argument to write syscall ; to make our output more interesting, combine tv_sec and tv_usec shl rax, 20 ; tv_usec only needs 20 bits or rax, rcx ; add tv_usec to the lower 20 bits .loop: mov ecx, eax ; take lower 32 bits of our value and ecx, 0xf ; only the lowest four bits movzx ebx, byte [rcx+hexchars]; and its hexchar mov [rsi+rdx], bl ; store at our output sub edx, 1 ; go backward in our output shr rax, 4 ; chop four bits we just did jnz .loop mov eax, 1 ; write syscall mov edi, 1 ; STDOUT argument to write mov edx, 17 ; length argument to write syscall add rsp, 40 ; clean up after ourselves mov eax, 60 ; exit (not group since we are only single threaded) xor edi, edi ; exit code syscall |
|||
11 Oct 2023, 20:05 |
|
edfed 11 Oct 2023, 20:54
i have an example too.
Code: print: ;eax = what to print ;return eax print it .hex: call eaxToHexadecimal ret or even a simpler code Code:
c:>hxd.exe
|
|||
11 Oct 2023, 20:54 |
|
revolution 11 Oct 2023, 22:43
edfed wrote: i have an example too. Code: flat assembler version 1.73.31 (16384 kilobytes memory) edfed.asm [5]: call eaxToHexadecimal processed: call eaxToHexadecimal error: undefined symbol 'eaxToHexadecimal'. edfed wrote:
Code: ~ c:>hxd.exe bash: c:: command not found ~ ls hxd.exe |
|||
11 Oct 2023, 22:43 |
|
Feryno 12 Oct 2023, 10:00
Somebody posted on FASM forum very efficient routine more than 10 years ago, maybe 15 y. I forgot the user name. Or maybe it was another forum.
Code: align 10h hexa_64_rax: ; put rax value to ASCII hexadecimal 16 byte buffer at [rdi] push rax bswap rax movdqa xmm3,dqword [Sum1] movdqa xmm4,dqword [Comp1] movdqa xmm2,dqword [Mask1] movdqa xmm5,dqword [Num1] movq xmm0,rax movdqa xmm1,xmm0 psrlq xmm0,4 pand xmm0,xmm2 pand xmm1,xmm2 punpcklbw xmm0,xmm1 movdqa xmm1,xmm0 pcmpgtb xmm0,xmm4 pand xmm0,xmm5 paddb xmm1,xmm3 paddb xmm1,xmm0 ; we must use movdqu instead of movdqa because we don't know if rdi is aligned 16 movdqu dqword [rdi],xmm1 pop rax ret align 10h hexa_64_rax_nobswap: movdqa xmm3,dqword [Sum1] movdqa xmm4,dqword [Comp1] movdqa xmm2,dqword [Mask1] movdqa xmm5,dqword [Num1] movq xmm0,rax movdqa xmm1,xmm0 psrlq xmm0,4 pand xmm0,xmm2 pand xmm1,xmm2 punpcklbw xmm0,xmm1 movdqa xmm1,xmm0 pcmpgtb xmm0,xmm4 pand xmm0,xmm5 paddb xmm1,xmm3 paddb xmm1,xmm0 movdqu dqword [rdi],xmm1 ret also put this into your data section and align it at 10h - if you do not align you can't use faster movdqa instruction and you have to use slower movdqu: Code: align 10h Sum1 dq 3030303030303030h, 3030303030303030h Mask1 dq 0f0f0f0f0f0f0f0fh, 0f0f0f0f0f0f0f0fh Comp1 dq 0909090909090909h, 0909090909090909h Num1 dq 0707070707070707h, 0707070707070707h edit: very likely it is here: https://board.flatassembler.net/topic.php?t=11162 |
|||
12 Oct 2023, 10:00 |
|
revolution 12 Oct 2023, 13:16
Feryno wrote: ... faster movdqa instruction and you have to use slower movdqu: Code: ; for INST in movdqa movdqu movdqa movdqu ; do fasm dqa-vs-dqu.asm -dLOOPS=999999999 -dOFFSET=0 -dINST=$INST >/dev/null && time ./dqa-vs-dqu ; done format elf64 executable SYS64_exit_group = 231 segment readable writeable executable align 16 values: db 16 * 32 dup 0 entry $ mov rcx,LOOPS .loop: rept 16 reg:0 { INST xmm#reg,[values + reg * 32 + OFFSET] } dec rcx jnz .loop mov eax,SYS64_exit_group xor edi,edi syscall Code: ~ for INST in movdqa movdqu movdqa movdqu ; do fasm dqa-vs-dqu.asm -dLOOPS=999999999 -dOFFSET=0 -dINST=$INST >/dev/null && time ./dqa-vs-dqu ; done real 0m2.037s user 0m2.024s sys 0m0.000s real 0m2.031s user 0m2.016s sys 0m0.000s real 0m2.033s user 0m2.024s sys 0m0.000s real 0m2.082s user 0m2.028s sys 0m0.000s |
|||
12 Oct 2023, 13:16 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.