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
Related
I wrote function in C that does work fine for me, but I need to write the same function in assembly. I generated assembly code of this function using `gcc -S rrd.c and I need some help in implementing it in asm. I'm using Linux, x86 assembly.
My C function:
double rrd (double a)
{
FILE *f=fopen("inital.txt","r");
if(f==NULL)
return 1;
double first, second;
do
{
fscanf(f, "%lf", &first);
fscanf(f, "%lf", &second);
}
while(a >= first);
close(f);
return second;
}
This is what I get:
http://pastebin.com/zyEBgTEC
And this is what I have so far:
.data
mode:
.string "r"
file:
.string "inital.txt"
format:
.string "%lf"
value:
.space 8
first:
.space 8
second:
.space 8
pointer:
.space 8
.text
.global re
re:
pushl %ebp
movl %esp, %ebp
fldl 8(%ebp)
fstpl value
pushl $mode
pushl $file
call fopen
movl %eax, pointer
cmpl $0, pointer
jne loop
jmp end
loop:
leal 16(%esp), %edx
pushl %edx
pushl $format
pushl pointer
call __isoc99_fscanf
leal 24(%esp), %edx
pushl %edx
pushl $format
pushl pointer
call __isoc99_fscanf
fldl 16(%esp)
fldl 32(%esp)
pushl pointer
call close
end:
leave
ret
Result after fldl instructions:
st0 -2.3534389814351579410727679528547297e-185 (raw 0xbd99ccccd5ffff9ac000)
st1 -1.9968719781118224876337308160145767 (raw 0xbfffff99804025016800)
My problem is that I don't exactly know where are the results of fscanf instructions and I don't know why there are those leal instructions.
Could anyone help me to rewrite this function?
So it should look like this:
wiecej:
leal pierwsza, %edx
pushl %edx
pushl $format
pushl wskaznik
call __isoc99_fscanf
leal druga, %edx
pushl %edx
pushl $format
pushl wskaznik
call __isoc99_fscanf
fldl pierwsza
fldl b
fucomip %st(1), %st
fstp %st(0)
setae %al
testb %al, %al
jne wiecej
fldl druga
I am learning loops and jumps in assembly and I try to make a simple loop. I want the printf command to be called 10 times. I have set the counter variable to 1. I have also set %edx to 1 and then I increment it for every iteration. If it is equal to 10, then we should exit the loop. But now the loop is infinite. I have debugged with gdb and %edx seems to be overwritten in the printf function. That is why I push %edx to the stack and the pop it back after the printf call, but it doesn't work. What have I missed?
.section .data
output:
.asciz "Value is %d\n"
val1:
.int 123
counter:
.int 1
.section .text
.globl _start
_start:
nop
movl counter, %edx # start at 1
gohere:
movl val1, %ebx # move value 123 to %ebx
pushl %edx # push %edx to stack
pushl %ebx # push %ebx to stack
pushl $output
call printf # call printf
popl %edx # pop %edx value
inc %edx
cmp $10, %edx # if %edx is less than 10...
jl gohere # ... go to gohere, otherwise exit
movl $0, %ebx
movl $1, %eax
int $0x80
you pushed output as the last push so the first pop will pop output. it is Stack and it is LIFO. in your code output will be in edx after you pop it.
to solve it put two pops before popl edx:
popl output
popl ebx
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
As sizeof operator evaluates operand if it's a VLA so I tried to test it as :
#include<stdio.h>
int main(void)
{
int sz=20,i=0,j=0;
int arr[sz];
printf("%d\n",sizeof((++i,sz)));
printf("%d\n",sizeof((++j,arr)));
printf("%d\n%d\n",i,j);
}
I thought that i won't increment as sz is not VLA but j would increment as arr is VLA.
But in the output, none of the i and j incremented.
Quoting my answer to another question:
The "conversion" is due to the subtraction operator. You can see a similar, and perhaps more surprising, result with the comma operator:
printf("%zu\n", sizeof(1, a));
will also print sizeof(int *), because of the comma operator resulting in a getting used in a value context.
Basically, due to the comma operator, the type of arr is a pointer, and the size of the VLA doesn't come into the picture. See my linked answer for details.
Not much of an explanation but I suspect it's some compiler optimization for the comma operator. The value of a comma operation is the value of the last expression. With the compiler knowing sizeof is a unary operator and presented with a comma operation, it doesn't bother to evaluate any but the last expression (regardless whether the last was a reference to a VLA or not).
I wrote some test programs (gcc 4.3.3 on Ubuntu 9.04):
$ cat test.c # with sizeof
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
sizeof( printf("%s%d\n", "comma!", ++x), x));
}
$ gcc -S test.c
$ cat test.s
.file "test.c"
.section .rodata
.LC0:
.string "%d\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 $36, %esp
movl $0, -8(%ebp)
movl $4, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $36, %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
Note the absences of the string literals and the second printf() call.
$ cat test-alt.c # without sizeof
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
( printf("%s%d\n", "comma!", ++x), x));
}
$ gcc -S test-alt.c
$ cat test-alt.s
.file "test-alt.c"
.section .rodata
.LC0:
.string "comma!"
.LC1:
.string "%s%d\n"
.LC2:
.string "%d\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 $36, %esp
movl $0, -8(%ebp)
addl $1, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, 8(%esp)
movl $.LC0, 4(%esp)
movl $.LC1, (%esp)
call printf
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC2, (%esp)
call printf
addl $36, %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
It may be documented somewhere but I wouldn't know where to look.
sizeof evaluates at compile time. In C99 for variable length arrays it will wait until runtime. Check this answer to a similar question.
Compiler knows the array size: it is obviously 20. I don't think that sz is VLA. Try to use use array size as function parameter, for eaxmple:
void Function(int size)
{
int arr[size];
...
}
BTW, to understand what happens, it is recommended to read Assembly code produced by compiler. Check whether sizeof is replaced by a constant already at compile time.
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. :)