AT&T sözdiziminden Intel Assembly ljmp sözdizimi

Dec 18 2020

Xv6 önyükleme kodunu At & t sözdiziminden Intel sözdizimine dönüştürmeye çalışıyorum ve ljmp talimatıyla ilgili bir sorunum var. Intel bilgisayarların önyükleme sürecini öğrenmeye çalışıyorum ve özellikle Intel montajında ​​güçlü değilim.

Orijinal AT&T sözdizimi .ljmp $0x8, $start32

Minimal örnek:

.code16
   jmp 0x8:start32          # won't assemble

.code32
start32:
   nop

as -32 -msyntax=intel -mnaked-reg foo.sGNU Binutils 2.35.1 ile kullanmak
Error: junk ':start32' after expressionuzak jmp satırı için üretir .

GNU as ve gcc araçlarını kullanıyorum.
Derlemede gdtdesc ve gdt gibi başka sorunlar da olabilir.

Intel sözdizimine taşınan kodun tamamı:

# Start the first CPU: switch to 32-bit protectied mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with cs = 0 and ip = 7c00.
.code16
.global start
start:
    # Disable interrupts.
    cli

    # Zero data segment registers DS, ES, and SS.
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax

seta20.1:
    # Wait for not busy.
    in al, 0x64
    test al, 0x2
    jnz seta20.1

    # 0xd1 -> port 0x64
    mov al, 0xd1
    out 0x64, al

seta20.2:
    # Wait for not busy.
    in al, 0x64
    test al, 0x2
    jnz seta20.2

    # 0xdf -> port 0x60
    mov al, 0xdf
    out 0x60, al

    # Switch from real to protected mode. Use a bootstrap GDT that makes
    # virtual addresses map directly to physical addressses so that the
    # effective memory map doesn't change during the transition.
    lgdt gdtdesc

    # Protection Enable in cr0 register.
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax

    # Complete the transtion to 32-bit protected mode by using a long jmp
    # to reload cs and eip. The segment descriptors are set up with no
    # translation, so that the mapping is still the identity mapping.

    # This instruction giving me problems.
    ljmp start32, 0x8

.code32
start32:
    # Set up the protected-mode data segment registers
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov ss, ax

    # Zero the segments not ready for use.
    xor ax, ax
    mov fs, ax
    mov gs, ax

    # Set up the stack pointer and call into C.
    mov esp, start
    call bootmain

    # If bootmain returns spin.. ??
spin:
    hlt
    jmp spin

# Bootstrap GDT set up null segment, code segment, and data segment respectively.
# Force 4 byte alignment.
.p2align 2
gdt:
    .word 0x0000, 0x0000
    .byte 0, 0, 0, 0
    .word 0xffff, 0x0000
    .byte 0, 0x9a, 0xcf, 0
    .word 0xffff, 0x0000
    .byte 0, 0x92, 0xcf, 0

# sizeof(gdt) - 1 and address of gdt respectively.
gdtdesc:
    .word (gdtdesc - gdt - 1)
    .long gdt

Yanıtlar

3 PeterCordes Dec 18 2020 at 11:58

Kullanabilirsiniz jmp 0x08, start32

Bazı nedenlerden dolayı, eşdeğer olması gereken komut satırı bağımsız değişkenleriyle bile jmp 0x8:start32yalnızca sonra çalışır .intel_syntax noprefix. Bu, Binutils tarafından kullanılan sözdizimidir objdump -d -Mintel -mi8086, ea 16 00 08 00 jmp 0x8:0x16yani muhtemelen bazen kabul edilmeyen bir GAS hatasıdır.


Sorunuzu, asJester'a verdiğiniz yanıtlara dayanarak 2.35.1 (Arch GNU / Linux'ta var) ile yeniden üretilebilir küçük bir örnek oluşturmak için düzenledim . Komut satırı seçeneklerini ekledim: .intel_syntax noprefixDosyanızda yönerge olmadığı için bunları kullanıyor olmanız gerektiğini varsayıyorum .

Bu sorun gibi görünüyor: -msyntax=intel -mnaked-reggibi diğer Intel sözdizimi işler yapar xor ax,ax, ama yok değil yapmak jmp 0x8:start32işi (ya da yazma başka yollar). Sadece .intel_syntax noprefix1 yönerge bu sözdiziminin jmp için çalışmasını sağlar.

# .intel_syntax noprefix        # rely on command line options to set this
.code16
   xor  ax, ax              # verify that command-line setting of intel_syntax worked, otherwise this line errors.

   ljmp 0x8, start32        # Working before or after a syntax directive, but is basically AT&T syntax
#   jmp 0x8:start32          # fails here, works after a directive
   jmp 0x8, start32         # Michael Petch's suggested syntax that's still somewhat AT&Tish.  works with just cmdline opts. 

.att_syntax
   ljmp $0x8, $start32      # working everywhere, even with clang
.intel_syntax noprefix
   jmp 0x8:start32          # objdump disassembly syntax, but only works after a .intel_syntax noprefix directive

.code32
start32:
   nop

Etkilerinin -msyntax=intel -mnaked-reggerekli olduğu diğer talimatlar için çalıştığını doğruladım : movzx ax, alişe yarıyor. Ama -mnaked-regolmasaydı, "çok fazla hafıza referansı" elde ederiz çünkü "ax" ve "al" sembol isimleri olarak alınırdı. Olmadan veya "işlenen boyut uyumsuzluğu" olmadan -msyntax=intel.

Listeleyen bir GAZ dan as -32 -msyntax=intel -mmnemonic=intel -mnaked-reg -o foo.o foo.s -al --listing-lhs-width=2 --listing-rhs-width=140
(eminim -mmnemonic=intelalakasız ve sözdizimi = intel ima budur.)

Makine koduna sahip oldukları için hangi talimatların çalıştığını ve hangisinin çalışmadığını (birincisi jmp 0x8:start32), çünkü sol taraftaki sütun boş olduğu için görebileceğinizi unutmayın . İlk sütun normalde adresler olacaktır, ancak ???? çünkü montaj başarısız oldu. (Çünkü jmp 0x8:start32ilk seferde başarısız olduğunu, 2. sefer çalıştığını göstermek için yorum yapmadım.)

foo.s: Assembler messages:
foo.s:6: Error: junk `:start32' after expression
GAS LISTING foo.s                       page 1


   1                            # .intel_syntax noprefix        # rely on command line options to set this
   2                            .code16
   3 ???? 0FB6C0                   movzx   ax, al              # verify that command-line setting of intel_syntax worked, otherwise this line errors.
   4                       
   5 ???? EA170008 00              ljmp 0x8, start32        # Working before or after a syntax directive, but is basically AT&T syntax
   6                               jmp 0x8:start32          # fails here, works after a directive
   7 ???? EA170008 00              jmp 0x8, start32         # Michael Petch's suggested syntax that's still somewhat AT&Tish.  works with just cmdline opts. 
   8                       
   9                            .att_syntax
  10 ???? EA170008 00              ljmp $0x8, $start32      # working everywhere, even with clang
  11                            .intel_syntax noprefix
  12 ???? EA170008 00              jmp 0x8:start32          # objdump disassembly syntax, but only works after a .intel_syntax noprefix directive
  13                       
  14                            .code32
  15                            start32:
  16 ???? 90                       nop
  17                       

(GAS, sol sütun için alan genişliklerini "kelimeler" olarak listeliyor, bu da 32 bitlik parçalar anlamına geliyor. Bu nedenle 00, segment seçicinin en önemli baytı bir boşlukla ayrılıyor.)

Bir etiketi koyarak öncejmp 0x8:label yardım etmedi; bu bir ileri ve geri referans sorunu değildir. jmp 0x8:23Montajı bile başarısız.


Çalışan bir derlemeden sökücüler tarafından "önerilen" sözdizimi:

objdump -drwC -Mintel -mi8086 foo.o :

foo.o:     file format elf32-i386

Disassembly of section .text:

00000000 <start32-0x17>:
   0:   0f b6 c0                movzx  ax,al
   3:   ea 17 00 08 00          jmp    0x8:0x17 4: R_386_16     .text
   8:   ea 17 00 08 00          jmp    0x8:0x17 9: R_386_16     .text
   d:   ea 17 00 08 00          jmp    0x8:0x17 e: R_386_16     .text
  12:   ea 17 00 08 00          jmp    0x8:0x17 13: R_386_16    .text

00000017 <start32>:
  17:   90                      nop

llvm-objdump --mattr=+16bit-mode --x86-asm-syntax=intel -d foo.o :

00000000 <.text>:
       0: 0f b6 c0                      movzx   ax, al
       3: ea 17 00 08 00                ljmp    8, 23
       8: ea 17 00 08 00                ljmp    8, 23
       d: ea 17 00 08 00                ljmp    8, 23
      12: ea 17 00 08 00                ljmp    8, 23

00000017 <start32>:
      17: 90                            nop

Ve BTW, bunun herhangi bir Intel-sözdizimi versiyonunu bir sembol adıyla birleştirmek için clang 11.0 almadım. ljmp 8, 12clang ile birleşir, ancak eşit değildir ljmp 8, start32. Sadece AT&T sözdizimine geçip geri dönerek, clang -m32 -masm=intel -c16 bitlik bir kipten uzak jmp yaymak için clang'ın yerleşik assembler ( ) elde edebilirim.

.att_syntax
   ljmp $0x8, $start32      # working everywhere, even with clang
.intel_syntax noprefix

Uzak JMP'nin bu doğrudan biçiminin 64 bit modunda kullanılamadığını unutmayın; belki de bu yüzden LLVM'nin yerleşik montajcısı, bunun için daha az çaba harcamış gibi görünüyor.


Dipnot 1: Aslında .intel_syntax prefixişe yarıyor ama onu asla kullanmayın. Kimse mov %eax, [%eax], ya da özellikle sipariş add %edx, %eaxkullanan dst, srcama AT&T ile dekore edilmiş kayıt isimleri olan franken-canavarı görmek istemez .

3 MichaelPetch Dec 18 2020 at 10:55

Sunduğunuz çevrilmiş kodun tamamında bu satır yanlıştır:

ljmp start32, 0x8

GNU Assembler'ın Intel sözdiziminde bir FAR JMP için uygun sözdizimi şöyledir:

ljmp 0x08, start32

Seçici değer birinci ve ofset ikinci olacaktır. Görünüşe göre AT&T sözdiziminden çevirirken, sıranın aynı kalması gerektiğinde bu 2 değeri tersine çevirdiniz. Değerler ters çevrildiğinde, hatayı alırsınız Error: can't handle non absolute segment in 'ljmp'. GNU'da Assembler Intel ayrıca yerini alabilir sözdizimi ljmpile jmpöylesine jmp 0x08, start32de çalışmak.

Intel sözdiziminin farklı türleri vardır. jmp 0x8:start32NASM'nin Intel sözdizimidir ve GNU Assembler'ın :ve ,farklı olduğu Intel sözdiziminden farklıdır. :İki değeri ayırmak için a kullandıysanız Error: junk ':start32' after expression, GNU Assembler'da hatayı alırsınız .


Notlar

  • Kod bootmainçalışmazsa, bu soruda sunduğunuz önyükleyici koduyla ilgili olmayan bir sorundur. Tüm C kodunu AT&T sözdizimi yerine Intel Sözdizimi ile oluşturuyorsanız, tüm satır içi derlemenin kaynak olarak doğru şekilde dönüştürüldüğünden ve işlenenin de tersine çevrildiğinden emin olun. xv6 olasılıkla dahil dosyaları bir dizi satır içi montaj vardır xv6-public/x86.h, xv6-public/spinlock.c, xv6-public/usertests.cvexv6-public/stressfs.c