flat assembler
Message board for the users of flat assembler.
Index
> Windows > Traversing a string |
Author |
|
ouadji 18 Jul 2011, 07:43
Code: ;eax == dword ... [myStr+ecx] == byte (because: byte *myStr) ;dword != byte => operand sizes do not match movzx eax,[myStr+ecx] |
|||
18 Jul 2011, 07:43 |
|
TmX 18 Jul 2011, 08:23
Now it compiles, but crashes
|
|||
18 Jul 2011, 08:23 |
|
bitshifter 18 Jul 2011, 08:40
I am guessing ECX is getting trashed by printf since it is not an ABI protected register.
Try using EBX or some other protected one... Also "%s" is to print string but you want to print char "%c" or just use putchar instead if you like... EDIT: Is this what your trying to do? Code: format PE console 4.0 include 'win32a.inc' entry start section '.data' data readable myStr db "Hello world", 0 fmt db "%c",13,10,0 section '.code' readable executable start: mov ebx, 0 repeat 11 mov eax, dword[myStr+ ebx] cinvoke printf, fmt, eax inc ebx end repeat invoke getchar invoke ExitProcess,0 section '.idata' data import readable writeable library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll' import kernel32,ExitProcess,'ExitProcess' import msvcrt,printf,'printf',getchar,'getchar' Last edited by bitshifter on 20 Jul 2011, 07:44; edited 1 time in total |
|||
18 Jul 2011, 08:40 |
|
ouadji 18 Jul 2011, 11:12
Code: start: mov esi,myStr repeat 11 lodsb cinvoke printf, fmt, eax end repeat invoke getchar invoke ExitProcess,0 start: mov esi,myStr @@: lodsb or al,al jz @F cinvoke printf, fmt, eax jmp @B @@: invoke getchar invoke ExitProcess,0 |
|||
18 Jul 2011, 11:12 |
|
edfed 18 Jul 2011, 12:12
wtf is that?
Code: myStr db "Hello world", 0 fmt db "%s\n",0 ;maybe db 13,10 can be cool!!! section '.code' readable executable start: mov ecx, 0 repeat 10 mov eax, [myStr+ ecx] cinvoke printf, fmt, eax inc ecx end repeat ;jmp can do that invoke ExitProcess,0 i think it can be good to do it with a string reconstruction, and cinvoke only one time. then, use a data buffer somewhere to compose the string to write (pick elements of string1, and interlace with repetitions of fmt. then, the result would be a string like that: Quote:
and will be possible to save as a text file, directlly useable anywhere. something like this: Code: str db "Hello world", 0 fmt db 13,10,0 alotofbytes=35793 ;a random value chosen for its sound in french new rb alotofbytes ;i'd prefer something like ES dynamic ram allocation, and more like proposed by our friends, using string instrucitons . section '.code' readable executable start: call buildstring cinvoke printf,new ;print the constructed string invoke ExitProcess,0 ;;;;;;;;;;;;;;;;; buildstring: push es ds pop es mov esi,str mov edi,new @@: lodsb or al,al je @f stosb call .interlace jmp @b @@: stosb ;end the string with 0 pop es ret ;;;;;;;;;;;;;;;;;; .interlace: mov eax,[fmt];load and insert the crlf sequence stosb ;just to don't use the 16 bit instruction stosw xchg al,ah ;use only 32 or 8 bits instructions stosb ;3 instructions instead of just two ret |
|||
18 Jul 2011, 12:12 |
|
ouadji 18 Jul 2011, 12:44
Quote:
Code: fmt dw 0x0A0D buildstring: push es ds pop es mov esi,str mov edi,new @@: lodsb or al,al jz @F stosb mov ax,[fmt] stosw jmp @B @@: stosb pop es ret |
|||
18 Jul 2011, 12:44 |
|
asmMe 18 Jul 2011, 12:52
here's a 29 byte buildstring
Code: buildstring: push es ds pop es mov esi, myStr mov edi, new mov eax, 0x000A0D00 @@: lodsb or al, al jz @f stosd ;stores byte + CR\LF in one go dec edi jmp @b @@: ;terminating 0 already written pop es ret |
|||
18 Jul 2011, 12:52 |
|
edfed 18 Jul 2011, 13:03
in fact, as mbr-tsr first coded, he want fmt to be "%s/n", then, only mov eax,dword[fmt] and stosd are needed in the buildstring.interlace subroutine.
i tested the code, the problem seems to be the ES segment parts. maybe we should do it with only the DS segment. |
|||
18 Jul 2011, 13:03 |
|
ouadji 18 Jul 2011, 13:23
28 bytes Code: buildstring: push es ds pop es mov esi,mystr mov edi,new mov eax,0x000A0D00 @@: lodsb stosd dec edi cmp byte[esi],0 jne @B pop es retd |
|||
18 Jul 2011, 13:23 |
|
ctl3d32 18 Jul 2011, 13:25
Let me have some fun too:
Code: format PE console 4.0 entry start include 'win32a.inc' HEAP_CREATE_ENABLE_EXECUTE = 0x00040000 section '.bss' readable writeable hHeap dd ? hBuffer dd ? BufferSize dd ? section '.data' data readable myStr db 'Hello world',0 fmt db '%s',0 section '.code' readable executable start: stdcall GetBufferNeededSize,myStr mov [BufferSize],eax invoke HeapCreate,HEAP_CREATE_ENABLE_EXECUTE,[BufferSize],512 mov [hHeap],eax invoke HeapAlloc,[hHeap],HEAP_ZERO_MEMORY,[BufferSize] mov [hBuffer],eax stdcall StringTransverse,[hBuffer],myStr cinvoke printf,fmt,[hBuffer] invoke getchar invoke ExitProcess,0 proc StrGetLength uses ecx edi,szString ;GET STRING LENGTH INCLUDING NULL TERMINATOR xor eax,eax mov ecx,0xffffffff mov edi,[szString] repne scasb not ecx mov eax,ecx ret endp proc GetBufferNeededSize uses ebx,szString ;GET SIZE OF BUFFER TO BE RESERVED stdcall StrGetLength,[szString] dec eax mov ebx,3 mul ebx inc eax ret endp proc StringTransverse uses ebx ecx,Buffer,szString ;TRANSVERSE THE STRING mov esi,[szString] mov ebx,[Buffer] xor ecx,ecx @@: lodsb test al,al je .finish mov byte[ebx+ecx],al mov word[ebx+ecx+1],0x0A0D ;CRLF add ecx,3 jmp @b .finish: ret endp section '.idata' data import readable writeable library kernel32,'kernel32.dll',\ msvcrt,'msvcrt.dll' include 'api\kernel32.inc' import msvcrt,\ printf,'printf',\ getchar,'getchar' Last edited by ctl3d32 on 18 Jul 2011, 15:11; edited 1 time in total |
|||
18 Jul 2011, 13:25 |
|
TmX 18 Jul 2011, 15:10
edfed wrote: wtf is that? Please bear with me. My background are HLLs like C or Java, and I'm still not used to 'think' in assembly yet |
|||
18 Jul 2011, 15:10 |
|
LocoDelAssembly 18 Jul 2011, 15:23
Code: format PE console 4.0 include 'win32a.inc' entry start section '.data' data readable myStr db "Hello world", 0 fmt db "%c", 10, 0 section '.code' readable executable start: mov ebx, 0 repeat 11 mov al, [myStr+ ebx] cinvoke printf, fmt, eax inc ebx end repeat cinvoke getchar invoke ExitProcess,0 section '.idata' data import readable writeable library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll' import kernel32,ExitProcess,'ExitProcess' import msvcrt,printf,'printf', getchar, 'getchar' Note however, that "repeat" is not a run-time thing, you are expanding the same code 11 times so you could have used this to not use a register for counting: Code: start: repeat 11 mov al, [myStr+ % - 1] cinvoke printf, fmt, eax ; Don't worry, printf will only use the lower byte of the dword end repeat cinvoke getchar invoke ExitProcess,0 But I'd do this way: Code: format PE console 4.0 include 'win32a.inc' entry start section '.data' data readable myStr db "Hello world", 0 myStr.sizeof = $ - myStr fmt db "%c", 10, 0 section '.code' readable executable start: mov ebx, -myStr.sizeof ; Other options are ESI, EDI, EBP, the rest of the registers can't be used because they are destroyed when printf returns print: mov al, [myStr + myStr.sizeof + ebx] cinvoke printf, fmt, eax ; Don't worry, printf will only use the lower byte of the dword inc ebx jnz print cinvoke getchar ; Just to wait freeze the console until <enter> is pressed invoke ExitProcess,0 section '.idata' data import readable writeable library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll' import kernel32,ExitProcess,'ExitProcess' import msvcrt,printf,'printf', getchar, 'getchar' |
|||
18 Jul 2011, 15:23 |
|
edfed 18 Jul 2011, 15:49
using the solution of ouadji, and deleting the push and pops, i have this result:
Code: use32 mystr equ 0 new equ 0 buildstring: mov edi,new mov esi,mystr mov eax,000a0d00h @@: lodsb stosd dec edi or al,al jne @b ret and it compiles in 23 bytes and in a fun test code, i have this: Code: format PE console 4.0 include 'c:/fasmw/include/win32a.inc' entry start section '.data' data readable writable exitdelay dd 800 spacetimes dd 0 .inc dd 8 .style dd "+-><" mystr db " Hell","o wo","rld",0 fmt db 13,10 alotofbytes=35793 ;a random value chosen for its sound in french new rb alotofbytes ;i'd prefer something like ES dynamic ram allocation, and more like proposed by our friends, using string instrucitons . db 0 section '.code' readable executable start: @@: call buildstring cinvoke printf,new ;print the constructed string call pong dec [exitdelay] jne @b invoke ExitProcess,0 ;;;;;;;;;;;;;;;;;;; pong: mov eax,[spacetimes.inc] add [spacetimes],eax jl .neg cmp [spacetimes],59 jl .ok .neg: neg [spacetimes.inc] sub [spacetimes],eax .ok: ret ;;;;;;;;;;;;;;;;;; buildstring: mov edi,new mov esi,mystr mov eax,000a0d00h @@: lodsb stosd dec edi call .spaces or al,al jne @b ; call .spaces ret ;;;;;;;;;;;;;;;;;;; .spaces: push eax ror dword[spacetimes.style],8 mov al,byte[spacetimes.style] mov ecx,[spacetimes] cmp ecx,0 jle @f rep stosb @@: pop eax ret ;;;;;;;;;;;;;;;;;; section '.idata' data import readable writeable library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll' import kernel32,ExitProcess,'ExitProcess' import msvcrt,printf,'printf' that outputs that: Quote:
|
|||
18 Jul 2011, 15:49 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.