ia32 Code mit einer ia64 CPU ausführen?



  • Hi,

    Ich wollte mal wieder etwas assembly programmieren(ia32, GNU Syntax) unter Linux.
    Leider habe ich eine 64-bit CPU.
    Meine Frage: Weiß jemand, wie es mit der Kompatibilität aussieht?

    Ich habe stark den Verdacht, dass es im Allgemeinen nicht kompatibel ist, da er mir manche Programme einfach nicht kompiliert.

    BSP:

    #schreibt den String auf die Konsole mithilfe von Linux-Syscall 4: WRITE
    
    .section .rodata
    message: .string "Hello GAS with IA32 Code \n"
    .equ sys_write, 0x4
    .equ stdout, 0x1
    
    .section .text
    .globl main
    .type main, @function
    
    main:
    
    #print
    mov	$sys_write , %eax
    mov	$stdout , %ebx 
    mov	$message, %ecx
    mov	$0x1A , %edx #26 Bytes
    
    int $0x80
    
    ret
    

    Dieser einfache Code funktioniert.

    Wenn aber z.B. der Stack mit ins Spiel kommt, gibt es Probleme.
    Speicheraddressen sind ja 64bit, da akzeptiert er natürlich pushl nicht mehr, sondern man müsste pushq nehmen.. das kann man noch recht einfach umschreiben.

    Aber bei Aufrufen von C-Funktionen komme ich an meine Grenzen.. kennt sich da jemand aus?
    Folgender Code funktioniert bei mir NICHT.. ich kriege einen libc-Aufruf einfach nicht zum Laufen. Es kompiliert, aber ich kriege einen Segmentation Fault.

    #schreibt string auf die Konsole
    #printf aus libc wird aufgerufen
    
    .section .data 
    	fmtstr: .string "Hello GAS. %s \n"
    	extstr: .string "Written using libc function call printf \n"
    .section .bss
    
    .section .text
    .globl main
    .type main,@function
    
    main:
    
    #Parameter auf den Stack schieben, printf aufrufen
    pushq	$extstr
    pushq	$fmtstr
    call	printf
    
    #Parameter für printf löschen
    add	$0x10, %esp
    
    mov	$1, %eax
    mov	$0, %ebx
    int	$0x80
    
    ret
    

    ALSO:
    Was läuft falsch? Kann mir jemand weiterhelfen? Sind das inkompatibilitätsprobleme, oder mache ich etwas falsch? Gibt es vllt. die Möglichkeit, ia32 Code auf einer ia64 auszuführen ?
    Anmerkung: Ich habe den gcc benutzt, unter as funktioniert es aber auch nicht.

    Danke schonmal für alle Antworten



  • triarii schrieb:

    ibt es vllt. die Möglichkeit, ia32 Code auf einer ia64 auszuführen ?

    Selbstverständlich (mal vorausgesetzt der Kernel wurde mit der entsprechenden Option gebaut), benötigt aber logischweise auch die jeweilige 32-bit Version der Bibliotheken, die genutzt werden - bei den meisten Distributionen in Hinblick auf glibc kein Problem.

    triarii schrieb:

    Was läuft falsch?

    Aufrufkonventionen nicht beachtet. Siehe ABI-Dokumention.

    Ganz nebenbei, wenn es nur 64-bit sein soll, ist es zweckmäßig, auch das entsprechende Kernelinterface zu verwenden.

    P.S. ia64 ist die falsche Bezeichnung, damit sind für gewöhnlich die 64-bit-Itaniums gemeint. amd64 oder x86_64 ist verständlicher.



  • triarii schrieb:
    ibt es vllt. die Möglichkeit, ia32 Code auf einer ia64 auszuführen ?
    Selbstverständlich

    Und wie würde das funktionieren? Muss man da anders kompilieren?

    Aufrufkonventionen nicht beachtet. Siehe ABI-Dokumention.

    Naja, in der ABI steht unter Aufrufkonventionen nur, dass Speicheraddressen auf dem Stack übergeben werden. Das habe ich doch gemacht?

    Übrigens, der gnu-debugger sagt, es kommt zu einem Segmenation Fault beim Aufruf von printf, weil:

    __printf (format=0x1 <error: Cannot access memory at address 0x1>)
       at printf.c:28
          printf.c: No such file or directory.
    

    Ich weiß leider immer noch nicht weiter 😞



  • triarii schrieb:

    triarii schrieb:
    ibt es vllt. die Möglichkeit, ia32 Code auf einer ia64 auszuführen ?
    Selbstverständlich

    Und wie würde das funktionieren? Muss man da anders kompilieren?

    Du musst die entsprechende 32-Bit Version der Libraries installieren. Kommt halt auf deine Distro an. Z.B. unter Arch Lnux brauchst du multilib und unter Ubuntu ist es (wenn ich mich richtig erinnere) ia32. Google einfach mal fuer deine Distro.

    Um 32-Bit Executables zu erstellen kannst du in gcc das -m32 Compiler-Flag verwenden.



  • triarii schrieb:

    Übrigens, der gnu-debugger sagt, es kommt zu einem Segmenation Fault beim Aufruf von printf, weil:

    __printf (format=0x1 <error: Cannot access memory at address 0x1>)
       at printf.c:28
          printf.c: No such file or directory.
    

    Ich weiß leider immer noch nicht weiter 😞

    In x86_64 werden die ersten paar Argumente in Registern uebergeben und nicht auf dem Stack. Schau dir mal die Aufrufkonvention fuer x86_64 an.

    PS: Sorry fuer DP



  • triarii schrieb:

    Naja, in der ABI steht unter Aufrufkonventionen nur, dass Speicheraddressen auf dem Stack übergeben werden.

    Das steht dort nicht.

    Seite 19 schrieb:

    Arguments of types (signed and unsigned) _Bool, char, short, int, long, long long, and pointers are in the INTEGER class.

    Seite 21 schrieb:

    Once arguments are classified, the registers get assigned (in left-to-right order) for passing as follows:
    1. ...
    2. If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used.

    Hast du das verlinkte Dokument überhaupt mal angeschaut?



  • Danke für eure Antworten.

    Ja, ich habe mir die ABI angesehen, aber mich verlesen, tut mir leid.
    Die Parameterübergabe funktioniert jetzt, so wie es dort beschrieben ist und ich kann jetzt die C-Funktionen aufrufen, danke 🙂

    Welche Bibliothek ich brauche, muss ich mal noch gucken. Ich hab Bodhi.