linux - [Solved-1 Solution] Assembling 32-bit binaries on a 64-bit system (GNU toolchain) - ubuntu - red hat - debian - linux server - linux pc



Linux - Problem :

Here write the assembly code that can be compiled:

as power.s -o power.o
click below button to copy the code. By - Linux tutorial - team

There is on problem when you link the power.o object file:

ld power.o -o power
click below button to copy the code. By - Linux tutorial - team

In order to run on the 64bit OS (Ubuntu 14.04), You included .code32 at the beginning of the power.s file, however you still get error:

Segmentation fault (core dumped)

power.s:

.code32
.section .data
.section .text
.global _start
_start:
pushl $3
pushl $2 
call power 
addl $8, %esp
pushl %eax 

pushl $2
pushl $5
call power
addl $8, %esp

popl %ebx
addl %eax, %ebx

movl $1, %eax
int $0x80



.type power, @function
power:
pushl %ebp  
movl %esp, %ebp 
subl $4, %esp 
movl 8(%ebp), %ebx 
movl 12(%ebp), %ecx 
movl %ebx, -4(%ebp) 

power_loop_start:
cmpl $1, %ecx 
je end_power
movl -4(%ebp), %eax
imull %ebx, %eax
movl %eax, -4(%ebp)

decl %ecx
jmp power_loop_start

end_power:
movl -4(%ebp), %eax 
movl %ebp, %esp
popl %ebp
ret
click below button to copy the code. By - Linux tutorial - team

Linux - Solution 1:

TL:DR: use gcc -m32.

  • .code32 does not change the output file format, and that's what determines the mode your program will run in.
  • It's up to you to not try to run 32bit code in 64bit mode.
  • .code32 is for assembling "foreign" machine code that you might need as data, or to export in a shared-memory segment.
  • If that's not what you're doing, avoid it so you'll get build-time errors when you build a .S in the wrong mode if it has any push or pop instructions for example.
  • Use the .S extension for hand-written assembler. (gcc foo.S will run it through the C preprocessor before as, so you can #include a header with syscall numbers, for example).
  • Also, it distinguishes it from .s compiler output (from gcc foo.c -O3 -S).

To build 32bit binaries, use one of these commands

gcc -g foo.S -o foo -m32 -nostdlib -static  # static binary with absolutely no libraries or startup code
                       # -nostdlib by itself makes static executables on Linux, but not OS X.
gcc -g foo.S -o foo -m32  # dynamic binary including the startup boilerplate code.  Use with code that defines a main() but not a _start
click below button to copy the code. By - Linux tutorial - team
  • Using libc functions from _start. Some functions, like malloc(3), or stdio functions including printf(3), depend on some global data being initialized (e.g. FILE *stdout and the object it actually points to).
  • gcc -nostartfiles leaves out the CRT _start boilerplate code, but still links libc (dynamically, by default).
  • On Linux, shared libraries can have initializer sections that are run by the dynamic linker when it loads them, before jumping to your _start entry point.
  • So gcc -nostartfiles hello.S still lets you call printf.
  • For a dynamic executable, the kernel runs /lib/ld-linux.so.2 on it instead of running it directly (use readelf -a to see the "ELF interpreter" string in your binary).
  • When your _start eventually runs, not all the registers will be zeroed, because the dynamic linker ran code in your process.
  • However, gcc -nostartfiles -static hello.S will link, but crash at runtime if you call printf or something without calling glibc's internal init functions.
  • Of course you can put any combination of .c, .S, and .o files on the same command line to link them all into one executable. If you have any C, don't forget -Og -Wall -Wextra: you don't want to be debugging your asm when the problem was something simple in the C that calls it that the compiler could have warned you about.
  • Use -v to have gcc show you the commands it runs to assemble and link. To do it "manually":
as foo.S -o foo.o -g --32 &&      # skips the preprocessor
ld -o foo foo.o  -m elf_i386

file foo
foo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped
click below button to copy the code. By - Linux tutorial - team

gcc -nostdlib -m32 is easier to remember and type than the two different options for as and ld (--32 and -m elf_i386). Also, it works on all platforms, including ones where executable format isn't ELF.


Related Searches to - linux - linux tutorial - Assembling 32-bit binaries on a 64-bit system (GNU toolchain)