8

I like to know how programs work so to make it as bare bones as possible I fool around with assembly.

I just found out how to assemble code for x86_64 using wprintf function (found out wide chars are 32 bit). all I had to do was link to libc (-lc).

I'm trying to assemble code for 32-bit doing about the same thing but I stumbled quite a bit. Eventually I used gcc to do the linking ( and changed the _start: to main:). So then I did the linking myself using ld and included crt1.o crti.o and crtn.o. Then my program worked ( it wouldn't print out anything before ) So my question is, can I do something within my code to eliminate the need for these other 3 object files (and of course revert back to _start: instead of main:)?

test_lib.S

.section .data
locale:
  .string ""
  .align 4
printformat:
  .long '%','l','c',0

.section .text
.global main
main:

pushl   $locale
pushl   $6
call    setlocale
pushl   $12414
pushl   $printformat
call    wprintf
pushl   $2
call    exit

and running the following

as --32 test_lib.S -o test_lib.o
ld -m elf_i386 -L/lib/ -L/usr/lib/ -I/lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o -lc /usr/lib/crtn.o test_lib.o -o test_lib
./test_lib

oh and the output is simply a japanese hiragana (ma)ま (notice there is no line break so it prints before the prompt)

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
Craig
  • 177
  • 2
  • 12

2 Answers2

8

Here are what the files do for you. They are the c-runtime environment and setup that link to the OS.

  • crt1.o Newer style of the initial runtime code. Contains the _start symbol which sets up the env with argc/argv/libc _init/libc _fini before jumping to the libc main. glibc calls this file 'start.S'.

  • crti.o Defines the function prolog; _init in the .init section and _fini in the .fini section. glibc calls this 'initfini.c'.

  • crtn.o Defines the function epilog. glibc calls this 'initfini.c'.

There is an excellent write up and example code to be found at the following website http://wiki.osdev.org/Creating_a_C_Library for each of the libraries above.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
Michael McGarrah
  • 585
  • 4
  • 10
  • well your link shows quite a bit of what I'm missing. Unfortunately it is based on the calling conventions of x86_64. I wonder where argc and argv are supposed to be in a 32-bit program. Also, why did my 64 bit program not need these files but my 32 bit one did? – Craig Aug 06 '13 at 23:50
  • I would assume the 32 versus 64 linker are pulling different defaults but I'm not sure. I've encountered differences between linkers in toolchains. – Michael McGarrah Aug 20 '13 at 18:40
  • Compiling without libc (http://stackoverflow.com/questions/2548486/compiling-without-libc) has additional good information. – Michael McGarrah Aug 20 '13 at 19:06
  • libc-start.c from the GNU Libc library would be a good starting point for the 32-code you are looking to find for the CRT (c-runtime) code above. – Michael McGarrah Aug 20 '13 at 19:08
  • Specifically, crtn.o finishes the .init and .fini sections started in crti.o. All it does for both sections is pop the stack pointer once. – enigmaticPhysicist May 14 '20 at 19:56
-1

In 3-bit Linux, they're on the stack. At start up, 0(%esp) contains argc. At 4(%esp), you'll find a pointer to the program name (which is included in argc). After that comes an array of pointers to the arguments, concluded with a NULL pointer. After that comes another NULL-concluded array of pointers to system variables. I am told that there may be over 200 of them!!

Shiarta

  • The question isn't asking about argc or argv, so it makes no sense to start off with the pronoun "they". There are already Q&As showing how to get argc and argv, and envp, from `_start`. – Peter Cordes Sep 29 '18 at 04:20