0

i got some problems with assembly code. I'm trying to call C function print. I compile file with:

gcc helloC.s -o hello

And i got error like:

 /tmp/cc0SwfB8.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status

This is a program given by our professor. I'm compiling by putty on univesity computer. Linux function: lscpu says it is x86_64 architecture.

Code given by our professor:

#PURPOSE: This program writes the message "hello world" and
# exits
#
.section .data
helloworld:
.ascii "hello world\n\0"
.section .text
.globl _start
_start:
main:
pushq $helloworld
call printf
pushq $0

call exit

The only thing i changed in this code is push -> pushq because of 64bit architecture.

Edit: as fuz said i changed .globl _start to .globl main. Olso i changed label _start: to main: I compiles without error.

When i lunch program with ./hello it says something like :"Memory protection violation" (translated form my native language. (Naruszenie ochrony pamięci))

#PURPOSE: This program writes the message "hello world" and
# exits
#
.section .data
helloworld:
.ascii "hello world\n\0"
.section .text
.globl main
main:
pushq $helloworld
call printf
pushq $0

call exit
PsiX
  • 1,661
  • 1
  • 17
  • 35
Fenrir
  • 151
  • 2
  • 14
  • 4
    Try adding `.globl main`. Also, remove the phony `_start` label and the associated `.globl _start` directive. You should not begin your program at `_start` if you use the libc. – fuz Apr 13 '18 at 14:48
  • EDITED. Now i have problem with memory. I hate assembly so much :( – Fenrir Apr 13 '18 at 15:08
  • After you get it to assemble and link, if you are indeed creating x86-64 bit programs (64-bit), the calling convention for 64-bit code is quite different than the CDECL calling convention for 32-bit code. You will need to read the System V Linux 64-bit (AMD64) ABI but you can find a summary here: https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI . Parameters are passed via registers at first (and then on the stack for functions with a lot of parameters), – Michael Petch Apr 13 '18 at 15:10
  • @Fenrir That's because the amd64 caling convention is not what you expect. You don't push arguments on the stack, you pass them in registers. Don't just assume how it works, read the documentation. – fuz Apr 13 '18 at 15:17
  • Well, i just wanted to see if it works. It seems that we can't compile example programs on univesity computers. Thats not good :( – Fenrir Apr 13 '18 at 15:45
  • 1
    You may be able to test this (assuming the system your on has the 32-bit GCC multiarch support, and the kernel has 32-bit support) by assembling this into a 32-bit program. You change pushq back to push, make the fix regarding main mentioned above, and then assemble and link with `gcc -m32 helloC.s -o hello` – Michael Petch Apr 13 '18 at 16:40
  • It works! Thank you @MichaelPetch – Fenrir Apr 13 '18 at 17:48
  • This may be useful: https://stackoverflow.com/questions/38335212/calling-printf-in-x86-64-using-gnu-assembler – Spock77 Apr 17 '18 at 16:51

2 Answers2

1

You cannot convert x86 assembly code to x64 assembly code mechanically like that.

Choose:

  • Compile for x86 and run.
  • Learn calling conventions and rewrite
  • rewrite in C

The reason you got memory protection violation is you called printf with arbitrary arguments. The first argument to printf goes in the rdi register in x64, not on the stack.

Joshua
  • 40,822
  • 8
  • 72
  • 132
-1

Try compiling it with the following commands:

as -o helloC.o helloC.s
ld -lc -s -o helloC helloC.o
Bram
  • 19
  • 5
  • Dynamically linking glibc on Linux does let its init functions run before `_start` (called from the dynamic linker), but it's generally not recommended. Also, many systems need you to specify the right path for the dynamic linker, because `ld`'s default is wrong for many modern x86-64 Linux distros. – Peter Cordes Apr 15 '18 at 21:26
  • And of course the OP's code is using the wrong calling convention for 64-bit (passing args on the stack like 32-bit), so even if this does assemble + link, it won't work. – Peter Cordes Apr 15 '18 at 21:27