3
votes

I'm reading the book: "Professional assembly language".
I want to use dynamic linking.
I'm using AT&T syntax with GNU assembler.
My computer has Ubuntu 12.04 (in a 64 bit system).
I'm trying to display the vendor ID string using the cpuid assembler opcode and
printf C function instead of linux system calls.

Code of hello.s

 .code32
   .section .data
 output:
   .asciz "The processor Vendor ID is '%s'\n"

 .section .bss
   .lcomm buffer, 12

 .section .text
   .globl _start
 _start:
   movl $0, %eax
   cpuid
   movl $buffer, %edi
   movl %ebx, (%edi)
   movl %edx, 4(%edi)
   movl %ecx, 8(%edi)
   pushl $buffer
   pushl $output
   call printf
   addl $8, %esp
   pushl $0
   call exit

I executed the next commands:

> $ as -o hello.o hello.s
> $ ld -dynamic-linker /lib/ld-linux.so.2 -o hello -lc hello.o
> $ ./hello
  bash: ./hello: Accessing a corrupted shared library

But I'm getting the error message shown above, something about a corrupted shared library (that's the error that I want to solve)
I don't care too much about the code (because I understand it)
I just want to learn how to use dynamic linking using assembly code and GAS.
So if you have any assembly code that uses dynamic linking I appreciate if you can show me the "as" and "ld" commands that you use.

PS: In case somebody wants to understand what does the code:
The CPUID instruction uses a single register value as input .
The EAX register is used to determine what information is produced by the CPUID instruction.
Depending on the value of the EAX register, the CPUID instruction will produce different information about the processor in the EBX, ECX, and EDX registers.
The information is returned as a series of bit values and flags, which must be interpreted to their proper meaning

This code utilizes the zero option (movl $0, %eax) to retrieve the simple Vendor ID string from the processor. When the value of zero is placed in the EAX register, and the CPUID instruction is executed, the processor returns the Vendor ID string in the EBX, EDX , and ECX registers as follows:

❑ EBX contains the low 4 bytes of the string.
❑ EDX contains the middle 4 bytes of the string.
❑ ECX contains the last 4 bytes of the string.

The string values are placed in the registers in little-endian format;
This code uses the standard C library functions: printf and exit instead of linux system calls.

1
A comment on each line of code would help us (a lot) to understand what your code is doing, and what you are trying to do with itUser.1
Try adding -m elf_i386 to the ld command line. Your .code32 may cover it, but you might want to try -32 to the (G)as command line, too. As you seem to understand, the trick is to convince your 64-bit tools that you want 32-bit code. Or you could write 64-bit code (not what's in your book). Or you could go back to system calls (easiest, IMO).Frank Kotler
If you intend to use the C library, you should use entry point main so that it has a chance to initialize. You should also compile and link using gcc -m32 -o hello hello.s, which is simple and does everything for you. You can pass -v option to see what exactly it is doing, but be prepared for a shock :)Jester

1 Answers

0
votes

I tried it as below, and it works:

as -32 -o hello.o hello.s
ld -melf_i386 -L/lib -lc -o hello hello.o

BTW, on my machine, it complains about missing /usr/lib/libc.so.1 , after I made a symbol link /usr/lib/libc.so.1 to /lib/ld-linux.so.2, it works.
create 32bit ELF on 64bit Linux, we need glibc.i686 or glibc.i386 installed.