.386
.model flat,c
.stack 100h
includelib msvcrt
.data
printf proto arg1:ptr byte
pointBuffer byte "Welcome",0
pointBuffer2 byte 12 dup(?),0
.code
public main
main proc
mov ecx,8
mov esi,offset pointBuffer
mov edi,offset pointBuffer2
while1: cmp ecx,0
je endloop
mov al,
mov ,al
inc edi
inc esi
dec ecx
cmp ecx,4
jge takepath1
jmp while1
endloop: nop
takepath1: invoke printf,addr pointBuffer2
jmp while1
ret
main endp
end main
im trying to do something so simple and i dont see why i cant have a invoke printf in a loop while having an if statment to execute it and jump back into loop
Posted on 2012-06-15 20:57:04 by hellfix
eax, ecx and edx are volatile registers, and are probably being overwritten by the call to printf, breaking your loop.
Right. And, in contrast, esi, edi, and ebx are "non-volatile" (esp and ebp too, but we're not concerned with them right now). They need to be "preserved". Hutch didn't like the term "preserved". Let's say: if you alter 'em, you have to put 'em back the way they were, before your function returns. Failure to do so may cause a crash! Might not, but we're "supposed" to do it. (the "proc" and "endproc" macros may do this for you?) Since you're using esi and edi, your choice for a loop counter is pretty obvious. If you have an "abnormal termination", "preserve" 'em!
An alternative would be to push and pop ecx around the call to printf.
Is ".stack 100h" correct in this context?
Best,
Frank
An alternative would be to push and pop ecx around the call to printf.
Is ".stack 100h" correct in this context?
Best,
Frank
(the "proc" and "endproc" macros may do this for you?)
Well, yes and no. I believe you have to explicitly specify the registers to save in the 'uses' clause (which depending on your point-of-view is another macro).
Is ".stack 100h" correct in this context?
I don't think it does anything. Normally it would create a .stack segment with the given size. But for 32-bit Windows binaries, the PE loader creates the stack for you. So I'm not sure what will happen. Perhaps the assembler will ignore it... or the assembler will emit a .stack section in the obj file, and the linker ignores it. Or perhaps the linker will link it into the PE file, and the PE loader ignores it...
At any rate, it is not required.
Thanks, Scali! Having any luck, Hellfix?
Best,
Frank
Best,
Frank
can anyone give me some sample code im still having trouble saving the registers and making a call to printf
Easiest way, probably...
That should clear up the problem that the call to printf is trashing your ecx. You still don't seem to have an exit condition to your loop.
Does calling your entrypoint "main" imply that this is called by C startup code? If not, "ret" may not provide a clean "ExitProcess". If so, you may still need to "preserve" (push/pop) esi and edi. This appears to be 32-bit code. Why is it in the dos/bios section? I may be confused about what you're trying to do...
Best,
Frank
endloop: nop
takepath1:
push ecx
invoke printf,addr pointBuffer2
pop ecx
jmp while1
; need a label here to jump to when ecx=0?
ret ; never reached?
That should clear up the problem that the call to printf is trashing your ecx. You still don't seem to have an exit condition to your loop.
Does calling your entrypoint "main" imply that this is called by C startup code? If not, "ret" may not provide a clean "ExitProcess". If so, you may still need to "preserve" (push/pop) esi and edi. This appears to be 32-bit code. Why is it in the dos/bios section? I may be confused about what you're trying to do...
Best,
Frank
im trying to print half of string being processed by the program then print a final message of the copied string heres what i came up with
.386
.model flat,c
.stack 100h
includelib msvcrt
.data
printf proto arg1:ptr byte
pointBuffer byte "Welcome",0
pointBuffer2 byte 12 dup(?),0
.code
public main
main proc
mov ebx,0
mov esi,offset pointBuffer
mov edi,offset pointBuffer2
while1: cmp ebx,8
jge endloop
mov al,
mov ,al
inc edi
inc esi
inc ebx
cmp ebx,4
je printOnce
jmp while1
printOnce: push offset pointBuffer2
call printf
cmp ebx,4
jbe while1
endloop: nop
push offset pointBuffer2
call printf
ret
main endp
end main
.386
.model flat,c
.stack 100h
includelib msvcrt
.data
printf proto arg1:ptr byte
pointBuffer byte "Welcome",0
pointBuffer2 byte 12 dup(?),0
.code
public main
main proc
mov ebx,0
mov esi,offset pointBuffer
mov edi,offset pointBuffer2
while1: cmp ebx,8
jge endloop
mov al,
mov ,al
inc edi
inc esi
inc ebx
cmp ebx,4
je printOnce
jmp while1
printOnce: push offset pointBuffer2
call printf
cmp ebx,4
jbe while1
endloop: nop
push offset pointBuffer2
call printf
ret
main endp
end main
First things first... "code tags". Put the word "code" between '[]'s at the beginning of your code and "/code" between '[]'s at the end of your code. The management thanks you. :)
I think you'll want that "uses ebx, esi, edi" here. I'm not sure what the syntax is - right after the "proc" or on a separate line? Try it until Masm doesn't complain. :) (or RTFM)
Strictly speaking, "jge" is for signed comparisons, "jae" is for unsigned. Won't hurt.
Okay... you've copied 3 characters - ebx incremented afterwards, remember. Might want 5 here?
Caller's responsibility to clean up stack!
We kinda knew it was 4 (or 5) or we wouldn't be here! An unconditional "jmp" should do here.
Outside of not "cleaning up the stack" (removing the parameter) after the call to printf, this doesn't look too bad. Another way to do this would be to "pop" a dummy register (ecx would do, since printf trashes it anyway). Also, I think you want to "preserve" ebx, esi, and edi. "Calling convention"! I think Agner Fog's got a document on it:
http://www.agner.org/optimize/
I'm not able to test this. There may be things I don't see, but I think it'll work. I think it'll print "WelWelcome" - might look better with a newline in there...
Best,
Frank
.386
.model flat,c
.stack 100h
includelib msvcrt
.data
printf proto arg1:ptr byte
pointBuffer byte "Welcome",0
pointBuffer2 byte 12 dup(?),0
.code
public main
main proc
I think you'll want that "uses ebx, esi, edi" here. I'm not sure what the syntax is - right after the "proc" or on a separate line? Try it until Masm doesn't complain. :) (or RTFM)
mov ebx,0
mov esi,offset pointBuffer
mov edi,offset pointBuffer2
while1: cmp ebx,8
jge endloop
Strictly speaking, "jge" is for signed comparisons, "jae" is for unsigned. Won't hurt.
mov al,
mov ,al
inc edi
inc esi
inc ebx
cmp ebx,4
je printOnce
Okay... you've copied 3 characters - ebx incremented afterwards, remember. Might want 5 here?
jmp while1
printOnce: push offset pointBuffer2
call printf
Caller's responsibility to clean up stack!
add esp, 4
cmp ebx,4
jbe while1
We kinda knew it was 4 (or 5) or we wouldn't be here! An unconditional "jmp" should do here.
endloop: nop
push offset pointBuffer2
call printf
add esp, 4 ; clean up stack!
ret
main endp
end main
Outside of not "cleaning up the stack" (removing the parameter) after the call to printf, this doesn't look too bad. Another way to do this would be to "pop" a dummy register (ecx would do, since printf trashes it anyway). Also, I think you want to "preserve" ebx, esi, and edi. "Calling convention"! I think Agner Fog's got a document on it:
http://www.agner.org/optimize/
I'm not able to test this. There may be things I don't see, but I think it'll work. I think it'll print "WelWelcome" - might look better with a newline in there...
Best,
Frank
This should help
.386
.model flat,c
includelib msvcrt
printf proto arg1:ptr byte
.data
pointBuffer byte "Welcome",0
szNewLine byte 13, 10 ,0
STRLEN equ $ - pointBuffer
.data?
pointBuffer2 byte 12 dup(?)
.code
public main
main:
push esi
push edi
push ebx
push ebp
mov esi, offset pointBuffer
mov edi, offset pointBuffer2
xor ebx, ebx
mov ebp, STRLEN
shr ebp, 2
while1:
mov al,
test al, al
jz endloop
mov , al
cmp ebx, ebp
je printOnce
inc ebx
jmp while1
printOnce:
push edi
call printf
add esp, 4 * 1
inc ebx
jmp while1
endloop:
push offset szNewLine
call printf
add esp, 4 * 1
push edi
call printf
add esp, 4 * 1
pop ebp
pop ebx
pop edi
pop esi
ret
end main