I am new in x86-64 assembly, and I am running a simple x64 assembly code:
.global main
.text
main:
mov $message, %rdi
sub $8, %rsp
call puts
add $8, %rsp
ret
message:
.asciz "Hello, World"
After compile the code using gcc under cygwin, it always return me the error:
segmentation error
but if I remove
call puts
the program runs without error. So what is the problem with this call out statement?
You must define message in the read only data section...
Like this...
.rodata # read-only data section
message:
.string "Hello, World!"
On 32-bit machine, with AT&T syntax, the code would be as follows...
.section .rodata
msg:
.string "Hello, World!" # msg is in the read only data section.
.section .text
.globl main
.type main, #function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $msg, (%esp) # We move the argument of puts to (%esp)
call puts # puts is called
movl $0, (%esp) # moved the argument of(0) exit to (%esp)
call exit # exit is called
Related
I have the following assembly code
.LC0:
.string "%d\n"
.text
.globl main
.type main, #function
main:
leaq .LC0(%rip), %rdi
movl $5, %esi
movl $0, %eax
call printf#PLT
Rather than print out 5, I want to print out the space between my current location and my first function (named func), I've been trying the following:
var1:
.long .-func
.LC0:
.string "%d\n"
.text
.globl main
.type main, #function
main:
leaq .LC0(%rip), %rdi
movl var1, %esi
movl $0, %eax
call printf#PLT
And I've tried
.size var1, .-func
.LC0:
.string "%d\n"
.text
.globl main
.type main, #function
main:
leaq .LC0(%rip), %rdi
movl var1, %esi
movl $0, %eax
call printf#PLT
Nothing I've tried has worked so far, any help would be much appreciated.
There is no way to access the size of a symbol as set with the .size directive. It's for debugging and some special cases involving common data areas only. To set var1 to .-func1, you can write
.set var1, .-func
This should work. Your second example should work, too. But without knowing what you expect it to do instead of what it is doing right now, that's hard to say.
Your attempt:
var1:
.long .-func
will make an object whose value is the distance between it and func. As I understand your question, you want the distance between the point of the call in main and func. So something like:
leaq .LC0(%rip), %rdi
movl $.-func, %esi
movl $0, %eax
call printf#PLT
Instead of ., you could use a label for a particular instruction in main, if needed.
The .size directive has nothing to do with what you want, although it's a common place you may have seen the .-symbol idiom. Its only purposes are debugging/disassembly assistance, making dladdr identify symbols that addresses belong to correctly, and (for data) making copy relocations work.
I have written simple code in order to study assembler.
Task im trying to do is in assembler part: mycode.s
Im curious, how would i be able to manually change position of my local variable int var ( it is located on stack, because its local) to lowest possible location(address) in stack...
Im using following code:
#include<stdio.h>
int c = 0;
int main()
{
int var = 0;
if( var == c)
{
printf("here");
}
return 0;
}
when i assemble my code with gcc -m32 -S mycode.c
i get:
.file "mycode.c"
.globl c
.bss
.align 4
.type c, #object
.size c, 4
c:
.zero 4
.section .rodata
.LC0:
.string "here"
.text
.globl main
.type main, #function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
movl $0, -12(%ebp)
movl c, %eax
cmpl %eax, -12(%ebp)
jne .L2
subl $12, %esp
pushl $.LC0
call printf
addl $16, %esp
.L2:
movl $0, %eax
movl -4(%ebp), %ecx
leave
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0"
.section .note.GNU-stack,"",#progbits
What instructions can i use to check the current stack addresses and find the lowest possible address (for example: 0x003 < 0x004).. Thanks
Good evening, i'm trying to translate this code of mine from C to assembly IA32:
int i=0;
char s[3]; char c[n];
for(i=0;i<3;i++){
s[i]=c[i];
}
n is a char that receives a value from user. By the time this "for" it's executing "c" is already filled with chars. I want, as you can see, fill "s" with the three first entries of "c". I translated this code to assembly like this:
.data
is: .asciz "%s"
id: .asciz "%d"
.bss
.comm c,500,1
.comm s,500,1
.comm n,4,4
.global main
main:
#asking for string to fill "c"
pushl $c
pushl $is
call scanf
addl $8,%esp
#asking for integer to know how long is c
pushl $n
pushl $id
call scanf
addl $8,%esp
movl $0,%eax
for:
cmpl $3,%eax
jge endfor
movb c(%eax),%cl
movb %cl,s(%eax)
incl %eax
jmp for
endfor:
movl $0,%eax
pushl %eax
pushl $s
pushl $is
call printf
addl $8,%ebp
popl %eax
Thing is when i execute this code it doesn't print anything at all, it's like "s" array it's empty, i've tried several things and nothing has worked so far. Any assembly genius to give me a hand?
:-) Thanks!
Following worked fine for me:
.data
is: .asciz "%s"
id: .asciz "%d"
.bss
.comm c,500,1
.comm s,500,1
.comm n,4,4
.text
.global main
main:
#asking for string to fill "c"
pushl $c
pushl $is
call scanf
addl $8,%esp
#asking for integer to know how long is c
pushl $n
pushl $id
call scanf
addl $8,%esp
movl $0,%eax
for:
cmpl $3,%eax
jge endfor
movb c(%eax),%cl
movb %cl,s(%eax)
incl %eax
jmp for
endfor:
movl $0,%eax
pushl %eax
pushl $s
pushl $is
call printf
addl $8,%esp
popl %eax
ret
Code belongs in .text, not in .bss
addl $8,%ebp near end should have been addl $8,%esp to fix stack pointer after printf call
needed ret at the end of main
you probably should explicitly store a nul terminator at the end of the string (unless you're expecting to copy it from the source string). I didn't make that change, however.
I don't think I changed anything else.
Assembled and linked with:
as -g -32 test.s -o test.o
gcc -g -m32 test.o
Input:
abc 3
Output:
abc
I wrote a simple program in c-language, the classic helloworld. I wanted to know how it looked liked when the compiler translated it to assembly code.
I use MinGW and the command:
gcc -S hellow.c
When I opened this file I expected it would, AT THE LEAST, be somewhat similar to a hello-world program written directly in assembly, that is:
jmp 115
db 'Hello world!$' (db = define bytes)
-a 115
mov ah, 09 (09 for displaying strings ... ah = 'command register')
mov dx, 102 (adress of the string)
int 21
int 20
Instead it look like this:
.file "hellow.c"
.def ___main;
.scl 2;
.type 32;
.endef
.section
.rdata,"dr"
LC0:
.ascii "Hello world!\0"
.text
.globl _main
.def _main;
.scl 2;
.type 32;
.endef
_main:
LFB6:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
call ___main
movl $LC0, (%esp)
call _puts
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE6:
.def _puts;
.scl 2;
.type 32;
.endef
I know litte about assembly language, but i DO recognice the so called mnemonics like ADD, POP, PUSH, MOV, JMP, INT etc. Could not see much of these in the code generated by the c-compiler.
What did I missunderstand?
This prepares the arguments to call a function __main that probably does all initial setup that is needed for a C program
andl $-16, %esp
subl $16, %esp
call ___main
This prepares the arguments and calls function _puts. LC0 is a symbol that contains the string to be printed.
movl $LC0, (%esp)
call _puts
This prepares the return value of main and returns
movl $0, %eax
leave
ret
Your example code uses Intel syntax, while the standard output from gcc is AT&T syntax. You can change that by using
gcc -S hellow.c -masm=intel
The resulting output should look more familiar.
However, if the compiler generates the source then it looks rather different, then what you would write by hand.
The int would be used if you compile for DOS, but even so, these calls would be wrapped in C standard functions, like puts in this case.
im just curious about the following example
#include<stdio.h>
int test();
int test(){
// int a = 5;
// int b = a+1;
return ;
}
int main(){
printf("%u\n",test());
return 0;
}
i compiled it with 'gcc -Wall -o semicolon semicolon.c' to create an executable
and 'gcc -Wall -S semicolon.c' to get the assembler code which is:
.file "semicolon.c"
.text
.globl test
.type test, #function
test:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
leave
ret
.size test, .-test
.section .rodata
.LC0:
.string "%u\n"
.text
.globl main
.type main, #function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
call test
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
movl $0, %eax
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",#progbits
since im not such an assembler pro, i only know that printf prints what is in eax
but i dont fully understand what 'movl %eax, 4(%esp)' means which i assume fills eax before calling test
but what is the value then? what means 4(%esp) and what does the value of esp mean?
if i uncomment the lines in test() printf prints 6 - which is written in eax ^^
Your assembly language annotated:
test:
pushl %ebp # Save the frame pointer
movl %esp, %ebp # Get the new frame pointer.
subl $4, %esp # Allocate some local space on the stack.
leave # Restore the old frame pointer/stack
ret
Note that nothing in test touches eax.
.size test, .-test
.section .rodata
.LC0:
.string "%u\n"
.text
.globl main
.type main, #function
main:
leal 4(%esp), %ecx # Point past the return address.
andl $-16, %esp # Align the stack.
pushl -4(%ecx) # Push the return address.
pushl %ebp # Save the frame pointer
movl %esp, %ebp # Get the new frame pointer.
pushl %ecx # save the old top of stack.
subl $20, %esp # Allocate some local space (for printf parameters and ?).
call test # Call test.
Note that at this point, nothing has modified eax. Whatever came into main is still here.
movl %eax, 4(%esp) # Save eax as a printf argument.
movl $.LC0, (%esp) # Send the format string.
call printf # Duh.
movl $0, %eax # Return zero from main.
addl $20, %esp # Deallocate local space.
popl %ecx # Restore the old top of stack.
popl %ebp # And the old frame pointer.
leal -4(%ecx), %esp # Fix the stack pointer,
ret
So, what gets printed out is whatever came in to main. As others have pointed out it is undefined: It depends on what the startup code (or the OS) has done to eax previously.
The semicolon has no return value, what you have there is an "empty return", like the one used to return from void functions - so the function doesn't return anything.
This actually causes a warning when compiling:
warning: `return' with no value, in function returning non-void
And I don't see anything placed in eax before calling test.
About 4(%esp), this means taking the value from the stack pointer (esp) + 4. I.e. the one-before-last word on the stack.
The return value of an int function is passed in the EAX register. The test function does not set the EAX register because no return value is given. The result is therefore undefined.
A semicolon indeed has no value.
I think the correct answer is that a return <nothing> for an int function is an error, or at least has undefined behavor. That's why compiling this with -Wall yields
semi.c: In function ‘test’:
semi.c:6: warning: ‘return’ with no value, in function returning non-void
As for what the %4,esp holds... it's a location on the stack where nothing was (intentionally) stored, so it will likely return whatever junk is found at that location. This could be the last expression evaluated to variables in the function (as in your example) or something completely different. This is what "undefined" is all about. :)