I have a problem I cant fix with a simple exercise my teacher assigned us.
I have this main.c that takes in a simple assembly function and I compile it with a make file, when I hit make run I get the following error :
"make: execvp: ./main: invalid argument make:***
[makefile:12:run] Error 127"
This is my make file:
main: main.o asm.o
gcc main.o asm.o -o main
main.o: main.c asm.h
gcc -Wall -g -c main.c -o main.o
asm.o: asm.s
gcc -Wall -g -c asm.s -o asm.o
run: main
./main
clean:
rm *.o main
My main.c file:
#include "asm.h"
int op1 = 0, op2 = 0, res = 0;
int main()
{
printf("Valor op1:");
scanf("%d", &op1);
printf("Valor op2:");
scanf("%d", &op2);
sum();
printf("sum = %d:0x%x\n", res, res);
return 0;
}
My asm.s:
.section .data
.global op1
.global op2
.global res
.section .text
.global sum # void sum(void)
sum:
movl op1(%rip), %ecx #place op1 in ecx
movl op2(%rip), %eax #place op2 in eax
addl %ecx, %eax #add ecx to eax. Result is in eax
movl %eax, res(%rip) # copy the result to res
ret
my asm.h:
#ifndef ASM_H
#define ASM_H
void sum();
#endif
Related
I have two files, one being main.c and the other prog2.s that contains assembly code. The commands I am running are:
gcc -Wall -g -m32 -c main.c
gcc -Wall -g -m32 -c prog2.s
gcc -Wall -g -m32 -o xtest main.o prog2.o
but on that last command, I am getting an error "undefined reference to 'prog2'" twice because in main.c, I try to call prog2 twice. I tried running the main.c file without the terminal but it produced the same error.
I'm not sure code is needed but so you get an idea of what I am trying to do, here are two code samples from each of the files up until the end of the first task which is to return j-i+2.
main.c
int prog2(int i, int j, int *k, int a[5], int *l);
int main() {
int k = 6;
int l = 0, res;
int a[5] = {7, 0, 8, 0, 3};
res = prog2(6,9,&k,a,&l);
if(res != 9-6+2) {
printf("return value should be=%d; got=%d\n", 9-6+2, res);
assert(0);
}
.globl prog2
prog2:
#Setup Code
pushl %ebp
movl %esp, %ebp
pushl %ebx
# j - i + 2
movl 12(%ebp), %eax
movl 8(%ebp), %ecx
subl %ecx, %eax
addl $2, %eax
I have my C program in 'main.c' and a function called list_equal() in 'list_equal.c'.
#include <stdlib.h>
#include "main.h"
int list_equal(const node_t *l1, const node_t *l2) {
while (l1!=NULL && l2!=NULL) {
if (l1->elem != l2->elem) return 0;
l1 = l1->next;
l2 = l2->next;
}
return l1==NULL && l2==NULL;
}
When I compile my program using:
$ gcc -m32 main.c list_equal.c -o main
everything worked fine and I was able to run my program './main'.
Then I translated my function in assembly code using AT&T syntax and named it "list_equal.s". Here's the code.
.globl list_equal
list_equal:
movl 4(%esp),%eax
movl 8(%esp),%ecx
L:
testl %eax,%eax
jz E
testl %ecx,%ecx
jz E
movw (%ecx),%dx
cmpw %dx,(%eax)
je F
movl $0,%eax
ret
E:
testl %eax,%eax
setz %al
testl %ecx,%ecx
setz %ah
andb %ah,%al
movsbl %al,%eax
ret
F:
movl 4(%eax),%eax
movl 4(%ecx),%ecx
jmp L
But when I try to compile my program again, this time using the assembly 'list_equal.s', with the command:
$gcc -m32 main.c list_equal.s -o main
I get this error message:
Undefined symbols for architecture i386:
"_list_equal", referenced from:
_test in main-bbda7f.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Thank you in advance.
Informations about my gcc compiler:
$ gcc --version
Configured with: --prefix=/Applications/Xcode_9.4.1.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode_9.4.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
The compiler prepends an underscore character at the function name.
You can see what the compiler generates if you call it like this:
gcc -S -m32 list_equal.c -o list_equal.c.s
Without -m32 there is no extra character.
This is my C code:
#include <stdio.h>
void sum();
int newAlphabet;
int main(void)
{
sum();
printf("%d\n",newAlphabet);
}
And this is my assembler code:
.globl _sum
_sum:
movq $1, %rax
movq %rax, _newAlphabet
ret
I'm trying to call the sum function, from my main function, to set newAlphabet equal to 1, but when I compile it (gcc -o test assembler.c assembler.s, compiled on a 64-bit OSX laptop) I get the following errors:
32-bit absolute addressing is not supported for x86-64
cannot do signed 4 byte relocation
both caused by the line "movq %rax, _newAlphabet"
I'm sure I'm making a very basic mistake. Can anyone help? Thanks in advance.
EDIT:
Here are the relevant portions of the C code once it has been translated to assembler:
.comm _newAlphabet,4,2
...
movq _newAlphabet#GOTPCREL(%rip), %rax
Mac OS X uses position-independent executables by default, which means your code can't use constant global addresses for variables. Instead you'll need to access globals in an IP-relative way. Just change:
movq %rax, _newAlphabet
to:
mov %eax, _newAlphabet(%rip)
and you'll be set (I changed from 64 to 32 bit registers to match sizeof(int) on Mac OS X. Note that you also need a .globl _newAlphabet in there somewhere. Here's an example I just made based on your code (note that I initialized newAlphabet to prove it works):
example.c:
#include <stdio.h>
void sum(void);
int newAlphabet = 2;
int main(void)
{
printf("%d\n",newAlphabet);
sum();
printf("%d\n",newAlphabet);
return 0;
}
assembly.s:
.globl _sum
.globl _newAlphabet
_sum:
movl $1, _newAlphabet(%rip)
ret
Build & run:
$ cc -c -o example.o example.c
$ cc -c -o assembly.o assembly.s
$ cc -o example example.o assembly.o
$ ./example
2
1
I have .s (x86 assembly at&t syntax) file, .h (header) file with struct defenition and functions decleration which are implemented in the assembly file, and main.c file with function call (from the .s file).
when trying to compile it all together, i get the following error:
main.o: In function `main':
/home/user/workspace/Assembly/main.c:7: undefined reference to `pstrlen'
collect2: error: ld returned 1 exit status
make: *** [a.out] Error 1
pstring.h:
typedef struct {
char len;
char str[255];
} Pstring;
char pstrlen(Pstring* pstr);
main.c:
#include <stdio.h>
#include "pstring.h"
int main() {
Pstring a;
a.len = 4;
printf("Length: %d", pstrlen(&a));
return 0;
}
pstring.s:
.file "pstring.s"
.section .rodata
invalid_input: .string "invalid input!\n"
.text
.type pstrlen, #function
pstrlen:
pushl %ebp
movl %ebp, %esp
movl 8(%ebp), %eax # assign given pstring ptr address to eax
movzbl (%eax), %ecx # set ecx with the value of the first byte (length) of the address at eax
movl %ecx, %eax # set return value as the value at ecx
ret
.type pstrcpy, #function
makefile:
a.out: main.o pstring.o
gcc -m32 -g -o a.out main.o pstring.o
main.o: main.c pstring.h
gcc -m32 -g -c -o main.o main.c
pstring.o: pstring.s
gcc -m32 -g -c -o pstring.o pstring.s
clean:
rm -f *.o a.out
Thank you.
I resolved the problem by declaring pstrlen as global as follows:
.text
.globl pstrlen
.type pstrlen, #function
pstrlen:
pushl %ebp
movl %ebp, %esp
movl 8(%ebp), %eax # assign given pstring ptr address to eax
movzbl (%eax), %ecx # set ecx with the value of the first byte (length) of the address at eax
movl %ecx, %eax # set return value as the value at ecx
ret
I have a NASM file and a C file. How do I call a function in the C file from the NASM file? How do I call a NASM function from the C file?
Many Thanks
DD
Calling assembly function from C:
C file:
#include <stdio.h>
int add(int a, int b);
int main(int argc, char **argv)
{
printf("%d\n", add(2, 6));
return 0;
}
assembly file:
global add
section .data
section .text
add:
mov eax, [esp+4] ; argument 1
add eax, [esp+8] ; argument 2
ret
compiling:
$ nasm -f elf add.asm
$ gcc -Wall main.c add.o
$ ./a.out
8
$
Calling C function from assembly:
C file:
int add(int a, int b)
{
return a + b;
}
assembly file:
extern add
extern printf
extern exit
global _start
section .data
format db "%d", 10, 0
section .text
_start:
push 6
push 2
call add ; add(2, 6)
push eax
push format
call printf ; printf(format, eax)
push 0
call exit ; exit(0)
compiling:
$ gcc -Wall -c add.c
$ nasm -f elf main.asm
$ ld main.o add.o -lc -I /lib/ld-linux.so.2
$ ./a.out
8
$