将 AT&T 转换为 INTEL 语法
Posted
技术标签:
【中文标题】将 AT&T 转换为 INTEL 语法【英文标题】:Translating AT&T to INTEL syntax 【发布时间】:2014-07-24 06:09:39 【问题描述】:我发现这个 GAS 文件包含一些可以从 CD 启动的引导加载程序代码,我想研究它并尝试自己制作一个,但唯一的问题是它是 AT&T 语法而不是英特尔语法,我对 AT&T 语法一无所知,我尝试使用 Intel2gas 转换器,但它没有完全转换它,然后我尝试转换它不能转换的东西,结果程序变得一团糟。
这是 intel2gas 输出的代码以及我尝试修复的代码:
;/* ISO-9660 boot sector
;* --------------------
;*
;* Copyright (c) 2008-2009 Frédéric Feret
;* All rights reserved.
;*
;* Features:
;* - supports ISO-9660 filesystem ("El Torito")
;* - supports multiples burning session
;* - no floppy emulation
;*
;* Limitations:
;* - supports only Joliet format
;*/
BITS 16
ORG 0x00
;/*
; * This is the main function of the boot sector, which loads the OS image
;* into memory at 1000:0000.
;*
;* Parameters:
;* DL = boot disk number.
;*/
;MISMATCH: " .global _start"
_start:
cli
; /* The Bios has loaded our boot sector at 0000:7C00. We move the code
; of this boot sector at 9000:0000. */
xor ax,ax
mov ds,ax
mov si,07C00h /* DS:SI = 0000:7C00. */
mov ax,09000h
mov es,ax
xor di,di /* ES:DI = 9000:0000. */
mov cx,00800h /* 2048 bytes. */
rep movsb /* do the relocation. */
;/* Jump to the new address. */
;MISMATCH: " ljmp $0x9000, $1f"
;.l1:
; /* Setup segment registers. */
mov ax,cs
mov ds,ax ; /* DS = CS = 9000. */
xor ax,ax
mov es,ax
mov ss,ax ;/* SS = ES = 0000. */
mov sp,07C00h ;/* SS:SP = 0000:7C00. */
; /* Save the boot disk number. */
mov [drive_number],dl
; /* Clear the screen. */
mov ax,003h
int 010h
mov si, msg_loading
call print_string
sti
; /* Check if the processor is a 386. */
pushf
pop ax ; /* FLAGS -> AX */
or ax,03000h ; /* try to set IOPL bits. */
push ax
popf ;/* AX -> FLAGS */
pushf
pop ax ;/* FLAGS -> AX */
test ax,03000h ;/* check if IOPL bits are always set */
jnz short .l1 ;/* it's a 386, or a higher model. */
;/* The processor is a 286 or even older model. We display an error message on the
; screen and then prompts the user to press a key on the keyboard to restart
; the computer. */
mov si, msg_no_386
call print_string
jmp reboot
.l1:
;/* Get the size in bytes of a sector from the BIOS. Normally, the size of
; a sector on a CD-ROM is 2048 bytes. */
mov word [disk_packet],01Ah
mov ah,048h
xor al,al
mov si, disk_packet
mov dl, [drive_number]
int 013h
jc assume_2k_sector
mov ax, disk_packet + 0x18
mov [bytes_per_sect],ax
jmp .l1
assume_2k_sector:
;/* An error occured while retrieving the size of a sector. We will display
; a warning message on the screen, then we assume that a sector on the
; disk makes 2 kilobytes. */
mov word [bytes_per_sect],00800h
mov si, msg_assume_2k_sector
call print_string
.l1:
;/* To load the OS image (which is located at the root directory of the disk),
; we have to look at all sessions of the disk. We will retrieve information
; on the root directory (its size and location) of each session, load the
;directory into memory and see if the OS image filename is in this directory.
;If the file isn't found, we move on to the next session. If all sessions
;were covered and that the filename wasn't found, we conclude that the OS
;image isn't on the disk. The first volume descriptor is the 17th sector of
;the disk. */
mov eax,16
get_next_desc:
;/* Read the sector in memory at 0000:1000. */
mov [desc_sector],eax
mov bx,01000h
mov cx,1
call read_sectors
;/* Check for the signature "\2CD001" at the beginning of the descriptor. */
mov si, cd_signature
mov di,01000h
mov cx,6
cmpsb
je found_desc
;/* Check if we have looked in all the descriptors of volume. */
cmp byte [%es:0x1000],0FFh
jne next_desc
;/* We looked in all sessions of the disk, and the OS image wasn't found.
; We display an error message on the screen and then prompts the user to
; press a key to restart the computer. */
mov si, msg_file_not_found
call print_string
jmp reboot
next_desc:
;/* Compute the next sector number to load. */
mov eax, [desc_sector]
inc eax
jmp get_next_desc
found_desc:
;/* We have to load a volume descriptor of a session in memory. We will check
; if the session supports the Joliet format for storing filenames and
; directories. Otherwise, the session is unknown. */
mov di,01058h
mov si, joliet_signature
mov cx,3
cmps
jne next_desc
;/* We found a session that supports Joliet format. We can find the size and
; the location of the root directory. */
mov eax, [es:0x109E]
mov [root_dir_start],eax
mov eax, [es:0x10A6]
mov [root_dir_size],eax
;/* Compute the number of sectors to load. */
movzx ebx,word [bytes_per_sect]
div ebx
cmp edx,0
je .l1
inc eax
.l1:
mov [root_dir_sectors],ax
;/* Read the root directory in memory at 0000:1000. */
mov eax, [root_dir_start]
mov bx,01000h
mov cx, [root_dir_sectors]
call read_sectors
;/* We will look into the root directory the OS image filename. If the file has
; been found, we save the sector number where that file ans its size in bytes.
; Otherwise, we move to the next session. */
mov di,01000h
search_file:
add di,25
;/* Check if this entry refers to a file. */
cmp byte [es:+di],0
jne next_entry
push di
add di,8
mov si, osimage
mov cx,14
cmps
pop di
je found_file ; /* file found? */
next_entry:
add di,7
movzx ax,byte [%es:+di]
add di,ax
.l1:
inc di
cmp byte [es:+di],0
je 1b
;/* Check if we have check all the entries of the root directory. */
mov eax, [root_dir_size]
add eax,01000h
cmp di,ax
jb search_file
;/* The OS image wasn't found in the root directory. We go to the next
; session of the disk. */
jmp next_desc
found_file:
sub di,25
;/* Get the location of this file. */
mov eax, [es:2+di]
mov [file_start],eax
;/* Get the size of this file. */
mov eax, [es:10+di]
mov [file_size],eax
/* Compute the number of sectors to load. */
movzx ebx,word [bytes_per_sect]
div ebx
cmp edx,0
je .l1
inc eax
.l1:
mov [file_sectors],ax
;/* Read the OS image in memory at 1000:0000. */
mov eax, [file_start]
mov bx,01000h
mov es,bx
xor bx,bx
mov cx, [file_sectors]
call read_sectors
mov dl, [drive_number]
xor si,si
;/* Run the OS loader... */
ljmp 0x1000:0x0000
;/*
; * This function loads one or more sectors in memory.
; *
; * Parmaeters:
; * EAX first sector to load.
; * CX number of sectors to load.
; * ES:BX destination address.
; */
read_sectors:
; /* To request the BIOS to load the sectors, we need to build a data
; packet that contains the number or sectors to load, the first
; logical sector to load and destination address. The address of
; this packet will then be given to the BIOS, which loads these
; sectors into memory. */
mov byte [disk_packet],010h
; /* We don't read one single sector at a time. */
mov disk_packet + 2, 0x01
; /* Write the destination address. */
mov disk_packet + 4, bx
mov disk_packet + 6, es
;/* Write the logical sector to load. */
mov disk_packet + 8, eax
mov disk_packet + 12, 0x0
read_one_sector:
;/* Read the sector into memory. */
mov ah,042h
xor al,al
mov si, disk_packet
mov dl, [drive_number]
int 013h;
jnc short .l1 /* read error? */
mov si, msg_read_error
call print_string
jmp reboot
.l1:
; /* Updates the next sector to load. */
inc disk_packet + 8
; /* Updates the destination address. Rather than incrementing the offset, we
; will increase the segment. */
mov ax, [bytes_per_sect]
shr ax,4
add disk_packet + 6, ax
loop read_one_sector
ret
;/*
;* This function displays a string to the screen, at the current cursor
;* position.
;*
;* Parameters:
;* DS:SI null-terminated string.
;*/
print_string:
; /* Read a character. */
repe lodsb
; /* Check if we reached the end of the string. */
cmp al,0
je short .l1
; /* Displays the character on screen. */
mov ah,00Eh
mov bx,007h
int 010h
jmp print_string
.l1:
ret
;/*
; * This function reboots the computer.
; */
reboot:
mov si, msg_reboot
call print_string
; /* Wait for a key. */
xor ax,ax
int 016h
; /* Rebooting... */
int 019h
;/*
; * Messages
; */
msg_loading: db '\n\rLoading...\n\n\r', 0
msg_no_386: db 'Error: 386 or higher processor required.\n\r', 0
msg_assume_2k_sector: db 'Error: failed to get sector size, assume 2 Kb.\n\r', 0
msg_file_not_found: db 'Error: OS image not found.\n\r', 0
msg_read_error: db 'Error: cannot read on disk.\n\r', 0
msg_reboot: db 'Press any key to restart your computer.\n\r', 0
;/*
; * Datas
; */
cd_signature: db 002h
db 'CD001'
joliet_signature: db 025h,02Fh,045h
MISMATCH: "osimage: .byte 0, 'o', 0, 's', 0, 'i', 0, 'm', 0, 'a', 0, 'g', 0, 'e'"
drive_number: db 0
bytes_per_sect: dw 0
root_dir_size: dd 0
root_dir_sectors: dw 0
root_dir_start: dd 0
file_size: dd 0
file_sectors: dw 0
file_start: dd 0
desc_sector: dd 0
disk_packet: RESB 020h
;/*
;* Boot sector signature
;*/
ORG 2046
dw 0AA55h
这是我尝试组装它时给我的所有错误
cdfs2.asm:34: error: expression syntax error
cdfs2.asm:37: error: expression syntax error
cdfs2.asm:38: error: expression syntax error
cdfs2.asm:39: error: expression syntax error
cdfs2.asm:47: error: expression syntax error
cdfs2.asm:50: error: expression syntax error
cdfs2.asm:51: error: expression syntax error
cdfs2.asm:67: error: expression syntax error
cdfs2.asm:68: error: expression syntax error
cdfs2.asm:70: error: expression syntax error
cdfs2.asm:73: error: expression syntax error
cdfs2.asm:74: error: expression syntax error
cdfs2.asm:75: error: expression syntax error
cdfs2.asm:133: error: expression syntax error
cdfs2.asm:197: error: symbol `cmps' redefined
cdfs2.asm:203: error: expression syntax error
cdfs2.asm:232: error: label or instruction expected at start of line
cdfs2.asm:253: error: parser: instruction expected
cdfs2.asm:289: error: expression syntax error
cdfs2.asm:363: error: parser: instruction expected
cdfs2.asm:378: error: program origin redefined
这是我用来组装的
nasm cdfs2.asm -o CD.iso
我已经修复了它,所以它现在可以组装,但是现在它给了我一个错误当我尝试将 ISO 加载到不支持格式的虚拟盒中我的猜测是因为上面的程序员所说的
;* Limitations:
;* - supports only Joliet format
有没有办法解决这个问题?这是转换后的代码:
;/* ISO-9660 boot sector
;* --------------------
;*
;* Copyright (c) 2008-2009 Frédéric Feret
;* All rights reserved.
;*
;* Features:
;* - supports ISO-9660 filesystem ("El Torito")
;* - supports multiples burning session
;* - no floppy emulation
;*
;* Limitations:
;* - supports only Joliet format
;*/
BITS 16
ORG 0x00
;/*
; * This is the main function of the boot sector, which loads the OS image
;* into memory at 1000:0000.
;*
;* Parameters:
;* DL = boot disk number.
;*/
;MISMATCH: " .global _start"
;_start:
cli
; /* The BIOS has loaded our boot sector at 0000:7C00. We move the code
; of this boot sector at 9000:0000. */
xor ax,ax
mov ds,ax
mov si,07C00h ; /* DS:SI = 0000:7C00. */
mov ax,09000h
mov es,ax
xor di,di ; /* ES:DI = 9000:0000. */
mov cx,00800h ; /* 2048 bytes. */
rep movsb ; /* do the relocation. */
;/* Jump to the new address. */
;MISMATCH: " ljmp $0x9000, $1f"
jmp 0x9000:here
here:
; /* Setup segment registers. */
mov ax,cs
mov ds,ax ; /* DS = CS = 9000. */
xor ax,ax
mov es,ax
mov ss,ax ;/* SS = ES = 0000. */
mov sp,07C00h ;/* SS:SP = 0000:7C00. */
; /* Save the boot disk number. */
mov [drive_number],dl
; /* Clear the screen. */
mov ax,003h
int 010h
mov si, msg_loading
call print_string
sti
; /* Check if the processor is a 386. */
pushf
pop ax ; /* FLAGS -> AX */
or ax,03000h ; /* try to set IOPL bits. */
push ax
popf ;/* AX -> FLAGS */
pushf
pop ax ;/* FLAGS -> AX */
test ax,03000h ;/* check if IOPL bits are always set */
jnz short .l1 ;/* it's a 386, or a higher model. */
;/* The processor is a 286 or even older model. We display an error message on the
; screen and then prompts the user to press a key on the keyboard to restart
; the computer. */
mov si, msg_no_386
call print_string
jmp reboot
.l1:
;/* Get the size in bytes of a sector from the BIOS. Normally, the size of
; a sector on a CD-ROM is 2048 bytes. */
mov word [disk_packet],01Ah
mov ah,048h
xor al,al
mov si, disk_packet
mov dl, [drive_number]
int 013h
jc assume_2k_sector
mov ax, disk_packet + 0x18
mov [bytes_per_sect],ax
jmp .l1
assume_2k_sector:
;/* An error occured while retrieving the size of a sector. We will display
; a warning message on the screen, then we assume that a sector on the
; disk makes 2 kilobytes. */
mov word [bytes_per_sect],00800h
mov si, msg_assume_2k_sector
call print_string
.l1:
;/* To load the OS image (which is located at the root directory of the disk),
; we have to look at all sessions of the disk. We will retrieve information
; on the root directory (its size and location) of each session, load the
;directory into memory and see if the OS image filename is in this directory.
;If the file isn't found, we move on to the next session. If all sessions
;were covered and that the filename wasn't found, we conclude that the OS
;image isn't on the disk. The first volume descriptor is the 17th sector of
;the disk. */
mov eax,16
get_next_desc:
;/* Read the sector in memory at 0000:1000. */
mov [desc_sector],eax
mov bx,01000h
mov cx,1
call read_sectors
;/* Check for the signature "\2CD001" at the beginning of the descriptor. */
mov si, cd_signature
mov di,01000h
mov cx,6
cmpsb
je found_desc
;/* Check if we have looked in all the descriptors of volume. */
cmp byte [es:0x1000],0FFh
jne next_desc
;/* We looked in all sessions of the disk, and the OS image wasn't found.
; We display an error message on the screen and then prompts the user to
; press a key to restart the computer. */
mov si, msg_file_not_found
call print_string
jmp reboot
next_desc:
;/* Compute the next sector number to load. */
mov eax, [desc_sector]
inc eax
jmp get_next_desc
found_desc:
;/* We have to load a volume descriptor of a session in memory. We will check
; if the session supports the Joliet format for storing filenames and
; directories. Otherwise, the session is unknown. */
mov di,01058h
mov si, joliet_signature
mov cx,3
cmpsb
jne next_desc
;/* We found a session that supports Joliet format. We can find the size and
; the location of the root directory. */
mov eax, [es:0x109E]
mov [root_dir_start],eax
mov eax, [es:0x10A6]
mov [root_dir_size],eax
;/* Compute the number of sectors to load. */
movzx ebx,word [bytes_per_sect]
div ebx
cmp edx,0
je .l1
inc eax
.l1:
mov [root_dir_sectors],ax
;/* Read the root directory in memory at 0000:1000. */
mov eax, [root_dir_start]
mov bx,01000h
mov cx, [root_dir_sectors]
call read_sectors
;/* We will look into the root directory the OS image filename. If the file has
; been found, we save the sector number where that file ans its size in bytes.
; Otherwise, we move to the next session. */
mov di,01000h
search_file:
add di,25
;/* Check if this entry refers to a file. */
cmp byte [es:+di],0
jne next_entry
push di
add di,8
mov si, osimage
mov cx,14
cmpsb
pop di
je found_file ; /* file found? */
next_entry:
add di,7
movzx ax,byte [es:+di]
add di,ax
.l1:
inc di
cmp byte [es:+di],0
je 1b
;/* Check if we have check all the entries of the root directory. */
mov eax, [root_dir_size]
add eax,01000h
cmp di,ax
jb search_file
;/* The OS image wasn't found in the root directory. We go to the next
; session of the disk. */
jmp next_desc
found_file:
sub di,25
;/* Get the location of this file. */
mov eax, [es:2+di]
mov [file_start],eax
;/* Get the size of this file. */
mov eax, [es:10+di]
mov [file_size],eax
;/* Compute the number of sectors to load. */
movzx ebx,word [bytes_per_sect]
div ebx
cmp edx,0
je .l1
inc eax
.l1:
mov [file_sectors],ax
;/* Read the OS image in memory at 1000:0000. */
mov eax, [file_start]
mov bx,01000h
mov es,bx
xor bx,bx
mov cx, [file_sectors]
call read_sectors
mov dl, [drive_number]
xor si,si
;/* Run the OS loader... */
jmp 0x1000:0x0000
;/*
; * This function loads one or more sectors in memory.
; *
; * Parmaeters:
; * EAX first sector to load.
; * CX number of sectors to load.
; * ES:BX destination address.
; */
read_sectors:
; /* To request the BIOS to load the sectors, we need to build a data
; packet that contains the number or sectors to load, the first
; logical sector to load and destination address. The address of
; this packet will then be given to the BIOS, which loads these
; sectors into memory. */
mov byte [disk_packet],010h
; /* We don't read one single sector at a time. */
mov [disk_packet + 2], word 0x01
; /* Write the destination address. */
mov [disk_packet + 4], bx
mov [disk_packet + 6], es
;/* Write the logical sector to load. */
mov [disk_packet + 8], eax
mov [disk_packet + 12], dword 0x0
read_one_sector:
;/* Read the sector into memory. */
mov ah,042h
xor al,al
mov si, disk_packet
mov dl, [drive_number]
int 013h
jnc short .l1 ; /* read error? */
mov si, msg_read_error
call print_string
jmp reboot
.l1:
; /* Updates the next sector to load. */
inc dword [disk_packet + 8]
; /* Updates the destination address. Rather than incrementing the offset, we
; will increase the segment. */
mov ax, [bytes_per_sect]
shr ax,4
add [disk_packet + 6], ax
loop read_one_sector
ret
;/*
;* This function displays a string to the screen, at the current cursor
;* position.
;*
;* Parameters:
;* DS:SI null-terminated string.
;*/
print_string:
; /* Read a character. */
repe lodsb
; /* Check if we reached the end of the string. */
cmp al,0
je short .l1
; /* Displays the character on screen. */
mov ah,00Eh
mov bx,007h
int 010h
jmp print_string
.l1:
ret
;/*
; * This function reboots the computer.
; */
reboot:
mov si, msg_reboot
call print_string
; /* Wait for a key. */
xor ax,ax
int 016h
; /* Rebooting... */
int 019h
;/*
; * Messages
; */
msg_loading: db `\n\rLoading...\n\n\r`, 0
msg_no_386: db `Error: 386 or higher processor required.\n\r`, 0
msg_assume_2k_sector: db `Error: failed to get sector size, assume 2 Kb.\n\r`, 0
msg_file_not_found: db `Error: OS image not found.\n\r`, 0
msg_read_error: db `Error: cannot read on disk.\n\r`, 0
msg_reboot: db `Press any key to restart your computer.\n\r`, 0
;/*
; * Datas
; */
cd_signature: db 002h
db 'CD001'
joliet_signature: db 025h,02Fh,045h
osimage: db 0, 'o', 0, 's', 0, 'i', 0, 'm', 0, 'a', 0, 'g', 0, 'e'
drive_number: db 0
bytes_per_sect: dw 0
root_dir_size: dd 0
root_dir_sectors: dw 0
root_dir_start: dd 0
file_size: dd 0
file_sectors: dw 0
file_start: dd 0
desc_sector: dd 0
disk_packet: times 020h db 0
;/*
;* Boot sector signature
;*/
; ORG 2046
times 2046 - ($ - $$) db 0
dw 0AA55h
【问题讨论】:
那么您的问题是什么?我们不会为您转换它。有什么不明白的地方请教intel2gas
转换器失败的地方。
我刚刚编辑它以获得它输出的代码
@bkausbk 我的问题是我将如何解决这个问题或从头开始并完全转换原件
如果您了解 Intel 语法,您可能需要一个小时的学习时间才能理解 AT&T 语法。如果您在 Linux 领域工作,您可能应该习惯阅读 AT&T 语法,即使它令人讨厌。
@JimMischel 有什么资源可以帮助我学习 AT&T 语法吗?
【参考方案1】:
唯一的问题是它是 AT&T 语法而不是 Intel 语法,我对 AT&T 语法一无所知
假设您对 Intel 语法 x86 程序集有一定的了解,下面简要总结一下 AT&T 语法中最重要的区别(取自 here):
注册命名
注册名称以%
为前缀。也就是说,如果必须使用eax
,则应使用%eax
。
来源和目的地排序
在任何指令中,源在前,目的在后。这与 Intel 语法不同,后者的源位于目标之后。
mov %eax, %ebx
,将eax
的内容传送给ebx
。
操作数的大小
指令后缀为b
、w
或l
,具体取决于操作数是字节、字还是长整数。这不是强制性的; GCC 尝试通过读取操作数来提供适当的后缀。但是手动指定后缀提高了代码的可读性,消除了编译器猜错的可能性。
movb %al, %bl -- Byte move
movw %ax, %bx -- Word move
movl %eax, %ebx -- Longword move
立即数
使用$
指定立即操作数。
movl $0xffff, %eax -- will move the value of 0xffff into eax register.
间接内存引用
任何对内存的间接引用都是通过使用( )
来完成的。
movb (%esi), %al -- will transfer the byte in the memory
pointed by esi into al register
【讨论】:
【参考方案2】:由于您提供了包含错误消息的转换文件,我们可以提供帮助。
cdfs2.asm:232: 错误:行首需要标签或指令
这个角色好像是 ;如果要使用 cmets,则需要。这里没有这个!
cdfs2.asm:253:错误:解析器:预期指令
没有ljmp
的助记词,请看Intel instruction set reference manual。无条件跳转的助记符是jmp
。
cdfs2.asm:363:错误:解析器:预期指令
字符串应以db
开头,如
MISMATCH: db 'osimage:', 0, 'o', 0, 's', 0, 'i', 0, 'm', 0, 'a', 0, 'g', 0, 'e'
cdfs2.asm:378: 错误:重新定义程序源
似乎不允许用“ORG”重新定义来源。
cdfs2.asm:197:错误:重新定义符号“cmps”
不允许使用隐式形式,应该是
CMPS ES:[DI]
cdfs2.asm:203: 错误:表达式语法错误
Cpu 寄存器 ES、DS、AX、BX、CX、DX...没有 AT&T 语法中的 % 前缀。
cdfs2.asm:34: 错误:表达式语法错误
cdfs2.asm:37: 错误:表达式语法错误
cdfs2.asm:38: 错误:表达式语法错误
cdfs2.asm:39: 错误:表达式语法错误
评论应以;
字符开头
这些信息可能有助于检测类似错误。
【讨论】:
"不允许使用隐式形式,应该是CMPS ES:[DI]
" -- NASM 语法实际上是cmpsb
,不允许使用“显式”形式。错误在于删除了“b”后缀,这也是 NASM 指令的一部分。以上是关于将 AT&T 转换为 INTEL 语法的主要内容,如果未能解决你的问题,请参考以下文章
如何将此代码从 Intel(nasm) 转换为 AT&T(gas) 语法?
如何在 i386 上将“推 2000”从 AT&T asm 转换为 Intel 语法
Linux下AT&T汇编语法格式与Intel汇编语法格式异同