assuming a C function like
what will be the address of variable x on the stack?? is it , , ,??
and in the case of
what will be the addresses of x and y??
int f( int x )
what will be the address of variable x on the stack?? is it , , ,??
and in the case of
int f ( int y, int x )
what will be the addresses of x and y??
It's been a long night, so forgive me if I don't get this exactly right, but ...
For most processors, the stack grows in the negative direction (decrementing), so once some data is placed on the stack (causing the esp to be adjusted in a negative direction), we can find the data at a positive offset of esp. If we have no stackframe, then the first input param is at esp+4 (since the return address is at esp+0)
For the x86 processor, most compilers will only use the ebp register for procedures which require a STACK FRAME - that means that the procedure has one or more LOCAL VARIABLES - otherwise we don't normally expect to see ebp being used.
In the cases where a stack frame is required, we'll normally see something like this:
Hope this is useful!
For most processors, the stack grows in the negative direction (decrementing), so once some data is placed on the stack (causing the esp to be adjusted in a negative direction), we can find the data at a positive offset of esp. If we have no stackframe, then the first input param is at esp+4 (since the return address is at esp+0)
For the x86 processor, most compilers will only use the ebp register for procedures which require a STACK FRAME - that means that the procedure has one or more LOCAL VARIABLES - otherwise we don't normally expect to see ebp being used.
In the cases where a stack frame is required, we'll normally see something like this:
MyStupidProcedure proc arg1:DWORD
LOCAL MyDumbVariable[16]:BYTE
push esp ;preserve value of esp on entry to procedure (for the return address)
mov ebp,esp ;we'll use ebp to access our stackframe (input params and any locals)
sub esp, 16 ;adjust esp to point PAST the locals so we dont trash anything on the stack
;do stuff in there
;example - we can safely push and pop since esp wont trash anything now
;example - first input param is now at ebp+8 since we pushed one dword onto the stack
pop esp ;restore the old esp so we can return to caller correctly
ret
MyStupidProcedure endp
Hope this is useful!
Ummm.... actually I don't think that is quite right...
I may not have this right, either. When we say "proc" and "endp", it generates some code (no? I avoid using 'em, myself...) so I may have done it twice...
Maybe helpful to look at the calling code...
When we "push x", x is at . The "call" pushes the return address on the stack (not obvious unless we RTFM). So now x is at (when we arrive at "f:").
With two parameters...
The called function "f" can look like:
Notice that this doesn't do "sub esp, localsize". It is possible to use local variables without a stack frame, but it's a PITA to keep track of where our parameters are, and to restore esp (the return address *must* be the next thing on the stack when we come to "ret"!!!). So it is common to use ebp as a "stack frame pointer"...
To further confuse the issue, a modern compiler (gcc, at least) doesn't actually use "push x", etc. It generates some more complicated - but faster - code... but it is equivalent...
Anyway, Ashken, the address of x (and y) depends on "when" - before the "call f", or after?
Are we confused yet? :)
Best,
Frank
MyStupidProcedure proc arg1:DWORD
LOCAL MyDumbVariable[16]:BYTE
; push esp ;preserve value of esp on entry to procedure (for the return address)
; no, no, no...
push ebp ; preserve caller's ebp - they're probably using it
mov ebp,esp ;we'll use ebp to access our stackframe (input params and any locals)
sub esp, 16 ;adjust esp to point PAST the locals so we dont trash anything on the stack
;do stuff in there
;example - we can safely push and pop since esp wont trash anything now
;example - first input param is now at ebp+8 since we pushed one dword onto the stack
; pop esp ;restore the old esp so we can return to caller correctly
; this would have popped from our "local variable" space, no?
mov esp, ebp ; restore esp - "free" local variables
pop ebp ; restore caller's ebp - now esp is what it was on entry
ret
MyStupidProcedure endp
I may not have this right, either. When we say "proc" and "endp", it generates some code (no? I avoid using 'em, myself...) so I may have done it twice...
Maybe helpful to look at the calling code...
; int f (int x)
push x
call f
add esp, 4
...
When we "push x", x is at . The "call" pushes the return address on the stack (not obvious unless we RTFM). So now x is at (when we arrive at "f:").
With two parameters...
; int f (int x, int y)
push y ; C pushes 'em right to left
push x
call f
add esp, 8
The called function "f" can look like:
; return address is at
mov ecx, ; x
mov edx, ; y
; do something with 'em
; mov eax, return value
ret
Notice that this doesn't do "sub esp, localsize". It is possible to use local variables without a stack frame, but it's a PITA to keep track of where our parameters are, and to restore esp (the return address *must* be the next thing on the stack when we come to "ret"!!!). So it is common to use ebp as a "stack frame pointer"...
; -> return address, x -> , y ->
push ebp ; save caller's ebp
; now x -> , etc
mov ebp, esp ; ebp = esp - stack frame pointer
; now x -> , y ->
sub esp, localsize ; if we want local variables
; now x ->
; but x still at - ain't that handy?
; do something
; get return value in eax
mov esp, ebp ; now esp is what it was after the "push ebp"
pop ebp ; and now esp -> return address, and caller's ebp is restored
ret
To further confuse the issue, a modern compiler (gcc, at least) doesn't actually use "push x", etc. It generates some more complicated - but faster - code... but it is equivalent...
Anyway, Ashken, the address of x (and y) depends on "when" - before the "call f", or after?
Are we confused yet? :)
Best,
Frank
I may not have this right, either. When we say "proc" and "endp", it generates some code (no? I avoid using 'em, myself...) so I may have done it twice...
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
MyStupidProcedure proc arg1:DWORD
LOCAL MyDumbVariable[16]:BYTE
push ebp ; preserve caller's ebp - they're probably using it
mov ebp, esp ;we'll use ebp to access our stackframe (input params and any locals)
sub esp, 16 ;adjust esp to point PAST the locals so we dont trash anything on the stack
;;----
;; Now, just to be clear: The 16 comes from the total size of all 'LOCAL' variables allocated,
;; so if we did a:
;; LOCAL myVarA:DWORD
;; LOCAL myVarB:WORD
;; LOCAL myVarC:DWORD
;; Then we would subtract ESP by (SIZEOF(DWORD) +SIZEOF(WORD) +SIZEOF(DWORD))
;; or simply: sub esp, (4*3).... HOLD UP!!! Now why did I do that? SIZEOF(WORD) is 2 not 4.
;; The reason I do that is to keep things aligned on the stack and to prevent any possible stalls.
;; Get used to doing this, always round up to the next dword if you can.
;;--
;do stuff in there
;example - we can safely push and pop since esp wont trash anything now
;example - first input param is now at ebp+8 since we pushed one dword onto the stack
; pop esp ;restore the old esp so we can return to caller correctly
; this would have popped from our "local variable" space, no?
mov esp, ebp ; restore esp - "free" local variables
pop ebp ; restore caller's ebp - now esp is what it was on entry
ret
MyStupidProcedure endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
Frank, yea, PROC/ENDP generate stuff, but MASM works using internal macros which can be "turned off" by setting the option to a NONE (empty macro) then resetting the default macro when you've finished your procedure. Cool thing about that feature is, it still preforms the argument variable translation for you so the code is still easy to read, you just have to do the stack init/cleanup yourself.
;; demo.asm - JWASM Epilogue & Prologue Demo
;; Build With:
;; jwasm -elf -zcw -Fo=demo.o demo.asm && gcc -s -nostartfiles -o demo demo.o
.386
.model flat, C
option casemap:none
%include @Environ(JWASM_INC)/jwasm.inc
.code
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
Say PROC msg:DWORD
push ebp
mov ebp, esp
invoke puts, msg
leave
ret
Say ENDP
OPTION EPILOGUE:EpilogueDef
OPTION PROLOGUE:PrologueDef
main PROC
invoke Say, CTEXT("Hello, World!")
xor eax, eax
ret
main ENDP
_start:
call main
xor ebx, ebx
xor eax, ebx
xor ebx, eax
xor eax, ebx
inc eax
int 80h
end _start
Wot?
I hope that's not supposed to clarify things for a beginner! If we're going to provide a "fake crt0.o" (the C "startup files"), shouldn't we fix up the stack before calling main? And what's that stuff after main returns? What if main doesn't return zero?
I haven't got any "jwasm.inc" on my system. I can see that, for this program, it needs to include "extern puts"... anything else? (or does Masm/Jwasm spell it "extrn"?)
Anyway, maybe Ashken can tell us which assembler he's using (makes a difference in syntax) and what OS (makes a difference whether we spell it "main" or "_main"), and perhaps we can come up with a more "precise" example that better illustrates the question at hand.
Best,
Frank
I hope that's not supposed to clarify things for a beginner! If we're going to provide a "fake crt0.o" (the C "startup files"), shouldn't we fix up the stack before calling main? And what's that stuff after main returns? What if main doesn't return zero?
I haven't got any "jwasm.inc" on my system. I can see that, for this program, it needs to include "extern puts"... anything else? (or does Masm/Jwasm spell it "extrn"?)
Anyway, maybe Ashken can tell us which assembler he's using (makes a difference in syntax) and what OS (makes a difference whether we spell it "main" or "_main"), and perhaps we can come up with a more "precise" example that better illustrates the question at hand.
Best,
Frank
assuming a C function like
int f( int x )
what will be the address of variable x on the stack?? is it , , ,??
Assuming 32-bit machine -
However note that most C compilers generate a prologue for each function that performs the following:
push ebp
mov ebp, esp
Thus you're most likely going to access your function parameters using ebp:
mov eax, ; get param X
:lol:
I hope that's not supposed to clarify things for a beginner! If we're going to provide a "fake crt0.o" (the C "startup files"), shouldn't we fix up the stack before calling main? And what's that stuff after main returns? What if main doesn't return zero?
What do is just call an 'int main( void )' function I don't do any argument initialization stuff like that and let GCC know that I don't want any startup code. On return, anything can be returned, that's the point of that craziness after the 'call main'. Basically it just zeros ebx, swaps the values in ebx and eax (since eax will have our return value from the procedure) then increments eax (which should be zero after the swap). So I'm basically doing sys_exit(main()); so that whatever main returns gets returned to the system... just in my own awkward little way. :lol:
I haven't got any "jwasm.inc" on my system. I can see that, for this program, it needs to include "extern puts"... anything else? (or does Masm/Jwasm spell it "extrn"?)
Yea, sorry about that. Force of habbit. The jwasm.inc file is like a wrap-up of all the standard headers (stdio.inc/stdlib.inc/etc.) and my base.mac from my personal include set. The only thing I'm actually using out of it is the CTEXT macro and the prototype for puts.
I hope that's not supposed to clarify things for a beginner! If we're going to provide a "fake crt0.o" (the C "startup files"), shouldn't we fix up the stack before calling main? And what's that stuff after main returns? What if main doesn't return zero?
What do is just call an 'int main( void )' function I don't do any argument initialization stuff like that and let GCC know that I don't want any startup code. On return, anything can be returned, that's the point of that craziness after the 'call main'. Basically it just zeros ebx, swaps the values in ebx and eax (since eax will have our return value from the procedure) then increments eax (which should be zero after the swap). So I'm basically doing sys_exit(main()); so that whatever main returns gets returned to the system... just in my own awkward little way. :lol:
I haven't got any "jwasm.inc" on my system. I can see that, for this program, it needs to include "extern puts"... anything else? (or does Masm/Jwasm spell it "extrn"?)
Yea, sorry about that. Force of habbit. The jwasm.inc file is like a wrap-up of all the standard headers (stdio.inc/stdlib.inc/etc.) and my base.mac from my personal include set. The only thing I'm actually using out of it is the CTEXT macro and the prototype for puts.
;; demo.asm - JWASM Epilogue & Prologue Demo
;; Build With:
;; jwasm -elf -zcw -Fo=demo.o demo.asm && gcc -s -nostartfiles -o demo demo.o
.386
.model flat, C
option casemap:none
CTEXT MACRO text:VARARG
LOCAL x
.CONST
IFIDNI <text>,<>
x DB 0
ELSE
x DB text, 0
ENDIF
.CODE
EXITM <OFFSET x>
ENDM
puts proto c :DWORD
.code
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
Say PROC msg:DWORD
push ebp
mov ebp, esp
invoke puts, msg
leave
ret
Say ENDP
OPTION EPILOGUE:EpilogueDef
OPTION PROLOGUE:PrologueDef
main PROC
invoke Say, CTEXT("Hello, World!")
xor eax, eax
ret
main ENDP
_start:
;; -- Good Demo of Why Commenting is Important Follows......
call main
xor ebx, ebx ; EBX := 0
xor eax, ebx ;
xor ebx, eax ;
xor eax, ebx ; EBX now holds the return value
inc eax ; SYS_exit
int 80h
end _start
Okay, on the assumption that "more is better" (not always true), and keeping in mind that we're addressing a beginner question...
But maybe what Ashken needs the comments on is:
Get into "enter" while we're here? Naw... ask if you wanna know, Ashken.
Best,
Frank
;; -- Good Demo of Why Commenting is Important Follows......
call main
; suppose main returns 42...
xor ebx, ebx ; EBX := 0
; xor anything with itself = 0
xor eax, ebx ;
; eax still 42, ebx still 0
xor ebx, eax ;
; now ebx = 42 also
xor eax, ebx ; EBX now holds the return value
; and eax = 0, 'cause we xor something with itself!
; this is the part I didn't get, first time through
inc eax ; SYS_exit
; SYS_exit is 1
int 80h
; this is for Linux, for those who don't know that.
But maybe what Ashken needs the comments on is:
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
Say PROC msg:DWORD
; this defines "msg" as ""
push ebp
mov ebp, esp
invoke puts, msg
; this is a macro which expands into:
; push msg - that is, push
; call puts
; add esp, 4 ; "remove" one parameter from stack
leave
; this is not a macro, but a real CPU instruction
; it does the same as:
; mov esp, ebp
; pop ebp
; (but does it in just one byte)
ret
Say ENDP
OPTION EPILOGUE:EpilogueDef
OPTION PROLOGUE:PrologueDef
Get into "enter" while we're here? Naw... ask if you wanna know, Ashken.
Best,
Frank
How about this...
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
SomeProc PROC arg1:DWORD, arg2:dword
LOCAL ddVar1:DWORD
LOCAL ddVar2:DWORD
push ebp
mov ebp, esp
sub esp, (4*2)
Reference | Base Pointer Relative | Stack Pointer Relative |
arg2 | EBP + 12 | ESP + 20 |
arg1 | EBP + 8 | ESP + 16 |
Ret Addr | EBP + 4 | ESP + 12 |
Old EBP | EBP + 0 | ESP + 8 |
ddVar1 | EBP - 4 | ESP + 4 |
ddVar2 | EBP - 8 | ESP + 0 |
leave
ret
SomeProc ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
Yeah! Now *that* answers the question! (P1ranha, too). I really thought that Homer made a typo, pushing esp where he meant ebp, and I got kinda sidetracked trying to clear that up...
You got it now, Ashken? (you still with us?)
Best,
Frank
You got it now, Ashken? (you still with us?)
Best,
Frank
thanx guys! am getting some concepts but some no!.anyway i just want the basic stuff mostly on interfacing between assembly and C ie calling C routines in ASM and vice versa.am using Nasm and the GCC based DJGPP trying to get a simple "Hello world" program. i tried this
NASM
and for C
i must be doing alot of things awfully i just got this error
Any help!! please!
NASM
;
;
;
segment .data
param db "%d",0
msg db "Hello world!",0
segment .bss
;
;
segment .text
global _start
extern _printf
_start:
push ebp
mov ebp,esp
sub esp,32
pusha
mov ecx,
mov edx,
push ecx
push edx
call _printf
pop edx
pop ecx
popa
mov esp,ebp
pop ebp
;and for C
int main()
{
int p;
p = start();
return p;
}
i must be doing alot of things awfully i just got this error
C:\DOCUME~1\vini\Desktop\src\PCASM~1\prep>gcc -o print.asm print.c
print.c:7:2: warning: no newline at end of file
c:/djgpp/tmp/ccShjznm.o:print.c:(.text+0x1d): undefined reference to `_start'
collect2: ld returned 1 exit status
Any help!! please!
ashken,
Wouldn't «gcc -o print.asm» use print.asm as output file name and overwrite it instead of compilation?
popa retrieves eax from stack too, probably clobbering start()'s return value.
And last, but not least: how start() is supposed to return back to its caller?
Wouldn't «gcc -o print.asm» use print.asm as output file name and overwrite it instead of compilation?
popa retrieves eax from stack too, probably clobbering start()'s return value.
And last, but not least: how start() is supposed to return back to its caller?
Yeah... you've got a number of small problems, including the ones baldr mentions. They can be fixed.
Now, before we can invoke gcc, we have to assemble this with Nasm - gcc won't handle it.
That should produce "print.obj", if all goes well. Now gcc was complaining about the lack of a newline in print.c, so you may want to make sure that ends on a blank line, but otherwise I think it's okay. As baldr points out, the "-o" switch to gcc sets the output file name, so you don't want the .asm filename there!
I think that should do it, barring typos, postos, and brainos. :) If not, pay close attention to the error messages. There's information in 'em (honest!).
"PCASM~1", eh? Using Dr. Carter's stuff? The warning isn't too big a deal (although we should try to avoid 'em!). As mentioned, you don't want "-o print.asm"!
The undefined reference to "_start" is because you didn't assemble the .asm file to an .obj file and include it on the command line to gcc. The underscore tells me that djgpp uses an underscore on externals - I should have remembered that, but Linux doesn't, and I wasn't sure. And it tells me that "start" is probably going to be an okay name for your function. If it were a "known entrypoint", as it is in Linux, I would expect "already defined" instead of "undefined reference". I could be wrong...
You might think about giving your function a more descriptive name (I suppose "start" is what you're doing). Maybe different names for the .c and .asm files, too. I think gcc will handle "print.obj" and "print.c" alright, but you could wind up with "print.obj" overwriting the other "print.obj" if you're not careful. :)
I like names like "mything.asm" and "callmything.c". but the "~1" in your error messages reminds me that you're limited to 8.3 filenames in djgpp. See, I told you there was information in 'em! :)
If you can't get it working from that, get back to us with details...
Best,
Frank
;
;
;
segment .data
param db "%d",0
; this is to print an integer. use "%s" for a zero-terminated string.
msg db "Hello world!",0
segment .bss
;
;
segment .text
global _start
; the name "_start" threw me for a loop! In Linux, "_start" is the name known to ld (the linker) as the default entrypoint. It may be okay in DJGPP, I'm not certain. You might want to call it "_my_asm_function" or something...
extern _printf
_start:
push ebp
mov ebp,esp
sub esp,32
pusha
; The only registers you explicitly use (besides ebp, which you save and restore correctly) are ecx and edx. You're allowed to trash them both (C calling convention). So you don't need to do this at all. As baldr points out, the "popa" will trash whatever is in eax - which is the value you want to return! Since you've reserved space for a local variable, that can be used to get around the problem. I'll show you, but I'd just not do "pusha" and "popa", if I were you. If you alter ebx, esi, or edi, you are expected to save and restore them (C calling convention). Since you don't...
; mov ecx,
; this loads the "" of memory - you want the address! Some assemblers use "offset" here, in Nasm syntax we just do:
mov ecx, msg
; mov edx,
; same here:
mov edx, param
push ecx ; "msg" first
push edx ; then "param"
; you could also have done:
; push msg
; push param
call _printf
; okay, printf returns number of items printed, as I recall. It'll be in eax.
pop edx
pop ecx
; since we don't care about the old values of ecx and edx, another way to "balance the stack" (which you need to do - C calling convention)...
; sub esp, 4 * 2 ; four bytes per parameter, two parameters
; the two pops are fine here - not as good if you've got many parameters
; since we're about to trash eax, we can stash it in a local variable:
; mov , eax
popa
; mov eax,
; as I said, I'd just not pusha/popa, but that saves eax temporarily
mov esp,ebp
pop ebp
; and of course you need a
ret ; !
Now, before we can invoke gcc, we have to assemble this with Nasm - gcc won't handle it.
nasm -f coff print.asm
That should produce "print.obj", if all goes well. Now gcc was complaining about the lack of a newline in print.c, so you may want to make sure that ends on a blank line, but otherwise I think it's okay. As baldr points out, the "-o" switch to gcc sets the output file name, so you don't want the .asm filename there!
gcc -o print.exe print.obj print.c
I think that should do it, barring typos, postos, and brainos. :) If not, pay close attention to the error messages. There's information in 'em (honest!).
C:\DOCUME~1\vini\Desktop\src\PCASM~1\prep>gcc -o print.asm print.c
print.c:7:2: warning: no newline at end of file
"PCASM~1", eh? Using Dr. Carter's stuff? The warning isn't too big a deal (although we should try to avoid 'em!). As mentioned, you don't want "-o print.asm"!
c:/djgpp/tmp/ccShjznm.o:print.c:(.text+0x1d): undefined reference to `_start'
collect2: ld returned 1 exit status
The undefined reference to "_start" is because you didn't assemble the .asm file to an .obj file and include it on the command line to gcc. The underscore tells me that djgpp uses an underscore on externals - I should have remembered that, but Linux doesn't, and I wasn't sure. And it tells me that "start" is probably going to be an okay name for your function. If it were a "known entrypoint", as it is in Linux, I would expect "already defined" instead of "undefined reference". I could be wrong...
You might think about giving your function a more descriptive name (I suppose "start" is what you're doing). Maybe different names for the .c and .asm files, too. I think gcc will handle "print.obj" and "print.c" alright, but you could wind up with "print.obj" overwriting the other "print.obj" if you're not careful. :)
I like names like "mything.asm" and "callmything.c". but the "~1" in your error messages reminds me that you're limited to 8.3 filenames in djgpp. See, I told you there was information in 'em! :)
If you can't get it working from that, get back to us with details...
Best,
Frank
@ashken:
According to your first post you have made a question other people did many times before too which doesn't need to be answered, actually.
Why don't you simply RTFM of your compiler about procedure parameter handling?!
I recommend WATCOM, which contains not only a very versatile C/FORTRAN compiler for almost any 16/32bit PC OS, but contains also all documentation about standard procedure parameter calling/return/structures/values... handling and their bending.
Download it for free and go through the manuals like I did here: ftp.openwatcom.org
According to your first post you have made a question other people did many times before too which doesn't need to be answered, actually.
Why don't you simply RTFM of your compiler about procedure parameter handling?!
I recommend WATCOM, which contains not only a very versatile C/FORTRAN compiler for almost any 16/32bit PC OS, but contains also all documentation about standard procedure parameter calling/return/structures/values... handling and their bending.
Download it for free and go through the manuals like I did here: ftp.openwatcom.org
BITS 32
EXTERN _printf
GLOBAL _SayHello
SECTION .text
_SayHello:
%define _arg1 EBP+8
push ebp
mov ebp, esp
push dword [_arg1]
push dword dbHelloWorld
call _printf
add esp, (4 * 2) ; Clean up stack after CDecl Call: (SizeOf(Dword) * ArgumentCount)
;; After a C Function you basically add up all the argument you pass then add that to esp to
;; correct the stack pointer. If you don't do this, it'll cause a segmentation fault when the function
;; returns.
leave
ret
SECTION .data
dbHelloWorld db " %d", 13, 10, 0
#include <stdio.h>
extern void SayIt( unsigned int );
int main( void )
{
SayIt(1);
SayIt(2);
SayIt(3);
return(0);
}
CC = gcc
AS = nasm
CFLAGS = -v -Wal
AFLAGS = -f coff
all: demo.exe
debug: demo.exe ; gdb ./demo.exe
demo.exe : demo.c SayHello.o ; $(CC) $(CFLAGS) main.c -o demo.exe SayHello.o
SayHello.o : SayHello.asm ; $(AS) $(AFLAGS) SayHello.asm -o SayHello.o
Use GNU Make to build these (they should do what you want) then run 'make debug'. Study what is going on in the debugger. Also, if you are getting used to intel syntax, I suggest modifying gdb to run in intel mode. Try the following .gdbinit script:
# .gdbinit - GDB Configuration File
define bpl
info breakpoints
end
document bpl
list breakpoints
end
define bp
break * $arg0
end
document bp
set a breakpoint on address
usage: bp addr
end
define bpc
clear $arg0
end
document bpc
clear breakpoint at function/address
usage: bpc addr
end
define bpe
enable $arg0
end
document bpe
enable breakpoint #
usage: bpe num
end
define bpd
disable $arg0
end
document bpd
disable breakpoint #
usage: bpd num
end
define bpt
tbreak $arg0
end
document bpt
set a temporary breakpoint on address
usage: bpt addr
end
define bpm
awatch $arg0
end
document bpm
set a read/write breakpoint on address
Usage: bpm addr
end
define syntax
set disassembly-flavor $arg0
end
document syntax
sets the current assembly syntax
usage: syntax
end
define regs
printf "\t--------------------------------\n"
printf "\teax: 0x%08X\tebx: 0x%08X\n", $eax, $ebx
printf "\tecx: 0x%08X\tedx: 0x%08X\n", $ecx, $edx
printf "\tedi: 0x%08X\tesi: 0x%08X\n", $edi, $esi
printf "\tesp: 0x%08X\tebp: 0x%08X\n", $esp, $ebp
printf "\teip: 0x%08X\n", $eip
printf "\t--------------------------------\n"
printf "\tcs: 0x%04X\tds: 0x%04X\n", $cs, $ds
printf "\tes: 0x%04X\tfs: 0x%04X\n", $es, $fs
printf "\tgs: 0x%04X\tss: 0x%04X\n", $gs, $ss
printf "\t--------------------------------\n"
printf "\t\tODITSZ_A_P_C\n\t\t"
if (($eflags >> 0xB) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 0xA) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 9) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 8) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 7) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 6) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 5) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 4) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 3) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 2) & 1)
printf "1"
else
printf "0"
end
if (($eflags >> 1) & 1)
printf "1"
else
printf "0"
end
if ($eflags & 1)
printf "1"
else
printf "0"
end
printf " = 0x%08X\n", $eflags
end
document regs
displays the cpu registers
end
define proc
info stack
info frame
info args
info locals
end
document proc
displays a lot of information about the current procedure
end
define procs
info functions
end
document procs
list all procedures in current process
end
define stack
info stack
end
document stack
displays the call stack
end
define vars
info variables
end
document vars
display the variables in the current process
end
define libs
info sharedlibrary
end
document libs
display shared libraries linked into the target
end
define sigs
info signals
end
document sigs
display signal actions for target
end
define threads
info threads
end
document threads
display threads in target
end
define dasm
disassemble $arg0
end
document dasm
disassemble code at address/label
usage: dasm
end
define start
tbreak _start
run
end
document start
run program; break on _start
end
define init
tbreak _init
run
end
document init
run program; break on _init
end
define main
tbreak main
run
end
document main
run program; break on _main
end
define lsmain
tbreak __libc_start_main
run
endm
document lsmain
run program; break on __libc_start_main
end
# Asm Simulations
define tcf
if ( $eflags & 1 )
set $eflags = $eflags &~ 1
else
set $eflags = $eflags | 1
end
end
document tcf
toggle carry flag
end
define tpf
if ( ($eflags >> 2) & 1 )
set $eflags = $eflags &~ 0x4
else
set $eflags = $eflags | 0x4
end
end
document tpf
toggle parity flag
end
define taf
if ( ($eflags >> 4) & 1)
set $eflags = $eflags &~ 0x10
else
set $eflags = $eflags | 0x10
end
end
document taf
toggle auxiliary flag
end
define tzf
if ( ($eflags >> 6) & 1 )
set $eflags = $eflags &~ 0x40
else
set $eflags = $eflags | 0x40
end
end
document tzf
toggle zero flag
end
define tsf
if ( ($eflags >> 7) & 1 )
set $eflags = $eflags &~ 0x80
else
set $eflags = $eflags | 0x80
end
end
document tsf
toggle sign flag
end
define ttf
if ( ($eflags >> 8) & 1 )
set $eflags = $eflags &~ 0x100
else
set $eflags = $eflags | 0x100
end
end
document ttf
toggle trap flag
end
define tif
if ( ($eflags >> 9) & 1 )
set $eflags = $eflags &~ 0x200
else
set $eflags = $eflags | 0x200
end
end
document tif
toggle interrupt flag
end
define tdf
if ( ($eflags >> 0xA) & 1 )
set $eflags = $eflags &~ 0x400
else
set $eflags = $eflags | 0x400
end
end
document tdf
toggle direction flag
end
define tof
if ( ($eflags >> 0xB) & 1 )
set $eflags = $eflags &~ 0x800
else
set $eflags = $eflags | 0x800
end
end
document tof
toggle overflow flag
end
define pb
set * (unsigned char *) $arg0 = $arg1
end
document pb
patch byte at address to value
usage: pb addr val
end
define pw
set * (unsigned short int *) $arg0 = $arg1
end
document pw
patch word at address to value
usage: pw addr val
end
define pd
set * (unsigned long int *) $arg0 = $arg1
end
document pd
patch dword at address to value
usage: pd addr val
end
# configuration defaults
set disassembly-flavor intel
set prompt \033[36m\033[39m\n: \b
I'm sure if you play around with GDB and the source, (and re-read some of these posts) you'll definitely get whats going on. You're almost there man! Hang in there. :)
Regards,
Bryant Keller
@ Frank, Homer and all the guys who have spent their precious time to help me out, thank you guys.you have given me what i wanted, i asked for a sandwich and you gave me just.your cutting edge solutions have solved my particular problem.Despite the fact that you knew compiler manuals existed, you didn't RTFM me and for that, maximum RESPECT!!!
oh! as for my first code which has lots of errors. i build it and it gave me a segmentation fault.
oh! as for my first code which has lots of errors. i build it and it gave me a segmentation fault.
Microsoft Windows XP
(C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\vini\Desktop\src\PC ASM\prep>print
Exiting due to signal SIGSEGV
General Protection Fault at eip=00006666
eax=48006425 ebx=00000000 ecx=00000011 edx=48006425 esi=00000054 edi=0000f588
ebp=0008f4e0 esp=0008e0bc program=C:\DOCUME~1\VINI\DESKTOP\SRC\PCASM~1\PREP\PRIN
T.EXE
cs: sel=01a7 base=02980000 limit=0009ffff
ds: sel=01af base=02980000 limit=0009ffff
es: sel=01af base=02980000 limit=0009ffff
fs: sel=017f base=000057a0 limit=0000ffff
gs: sel=01bf base=00000000 limit=0010ffff
ss: sel=01af base=02980000 limit=0009ffff
App stack: [0008f588..0000f588] Exceptn stack: [0000f4e8..0000d5a8]
Call frame traceback EIPs:
0x00006666
0x000031d6
0x000015fd
0x00001631
0x00002dd8
C:\DOCUME~1\vini\Desktop\src\PCASM~1\prep>
Just a few notes about your previous code....
Read the comments, there are a few places where things could have gone wrong, most likely the "FIXED" sections. I've made a few other modifications simply because I don't feel comfortable re-releasing the code without pointing out the issues with them. :p
segment .data
param db "%s",0 ; FIXED: %d is for integers, %s is for strings.
msg db "Hello world!",0
;; This isn't needed, you're not using a BSS section.
;segment .bss
segment .text
global _Entry
extern _printf
;; I'm not comfortable with this name, Lets change it to Entry
;_start:
_Entry:
push ebp
mov ebp,esp
;; Why do you allocate local variables at all?
;; You're not using any. Again, unneeded.
;sub esp,32
pusha
mov ecx, msg ; FIXED: We want the ADDRESS of the label, not the contents of the memory.
mov edx, param ; FIXED: We want the ADDRESS of the label, not the contents of the memory.
push ecx
push edx
call _printf
pop edx
pop ecx
;; This could easily be done with ADD ESP, (4 * 2)
popa
mov esp,ebp
pop ebp
;; FIXED: You are missing a RETurn here.
ret
Read the comments, there are a few places where things could have gone wrong, most likely the "FIXED" sections. I've made a few other modifications simply because I don't feel comfortable re-releasing the code without pointing out the issues with them. :p
Just on inspection... "unresolved external _SayIt"... (since the global function in the .asm file is called "_SayHello"...) :) The fix is obvious. Nice example, as it shows passing a parameter, which we weren't doing. The ".gdbinit" should be a big help!
TasmDev, why do you think Watcom is superior to gcc? Oh, I know - Tasm won't produce COFF. Easily fixed - http://www.nasm.us :) If you try it, Ashken, trailing underscores, not leading... Nice compiler, but a little "oddball".
SIGSEGV at 0x00006666 - jeez, it's the number of the beast on steroids! :) Almost certainly failure to "clean up" the stack properly somewhere, I would guess... Lack of the "ret" would do it, also. If you can't fix it, post the exact code that produced it.
As for RTFM, excellent advice! Puts *me* to sleep, though... :)
Best,
Frank
TasmDev, why do you think Watcom is superior to gcc? Oh, I know - Tasm won't produce COFF. Easily fixed - http://www.nasm.us :) If you try it, Ashken, trailing underscores, not leading... Nice compiler, but a little "oddball".
SIGSEGV at 0x00006666 - jeez, it's the number of the beast on steroids! :) Almost certainly failure to "clean up" the stack properly somewhere, I would guess... Lack of the "ret" would do it, also. If you can't fix it, post the exact code that produced it.
As for RTFM, excellent advice! Puts *me* to sleep, though... :)
Best,
Frank
I'm going to have to get sp00k to install an "asshat counter" on the forum for me so I can keep track of how many times I've built something that worked fine, then made a last minute change (like modifying the name of a procedure or removing a macro) that has completely fubar the source. lmfao 8) Thanks for the catch man. The "SayIt"'s should definitely be "SayHello"'s, lol.