我在80836 DOS程序集中找到了代码,我希望使用AT& T语法将其移植到32位Linux程序集。
我发现网站解释了一些差异,但只是关于寄存器。 EX:
所以我在转换以下代码时遇到了问题:
input:
mov ah, 00h
int 16h
cmp ah, 1ch
je exit
sub al, 30h
sub al, 37h
sub al, 57h
mov ah, 02h
mov dl, al
int 21h
mov dl, 20h
int 21h
exit:
int 20h
我正在转换this code
我认为:
最糟糕的问题是中断,因为在AT& T组件中它就像:
SYSCALL = 0X80
SYSEXIT = 1
EXIT_SUCCESS = 0
SYSREAD = 3
SYSWRITE = 4
STDIN = 0
STDOUT = 1
在DOS16,16h? 20H? 21H?哦,伙计,即使那时int 20h充当中断和值(mov dl,20h)?太混乱了。
有人可以帮助我吗?
@EDIT 我这样转换它,但是我得到了分段错误错误。我几乎肯定这是关于中断..
.data
.text
.global _start
_start:
input:
movb $0x0,%ah
int $0x16
cmpb $0x1c,%ah
je exit
number:
cmpb $'0', %al
jb input
cmpb $'9', %al
ja uppercase
subb $0x30,%al
call process
jmp input
uppercase:
cmpb $'A', %al
jb input
cmpb $'F', %al
ja lowercase
subb $0x37,%al
call process
jmp input
lowercase:
cmpb $'a', %al
jb input
cmpb $'f', %al
ja input
subb $0x57,%al
call process
jmp input
loop input
process:
movb $4,%ch
movb $3,%cl
movb %al,%bl
convert:
movb %bl,%al
rorb %cl,%al
andb $01,%al
addb $0x30,%al
movb $0x2,%ah
movb %al,%dl
int $0x21
decb %cl
decb %ch
jnz convert
movb $0x20,%dl
int $0x21
ret
exit:
int $0x20
任何?
答案 0 :(得分:3)
您的代码“转换”的主要问题可能是您似乎将某些想法与“80836 assembly”和“at& t”这些并不真正适用的术语联系起来。
虽然这可能仅仅是命名约定的问题,但是没有“80386汇编”与“at& t”的区别,但是“intel”与“at& T语法”的差异为两者 intel语法和at& t语法可用于描述x86汇编代码。
如果您使用的是GNU汇编程序(我不知道任何其他x86汇编程序使用AT& T语法而不是intel),您可能只想使用.intel_syntax
并继续使用参考资料中使用的intel语法代替。
.intel_syntax noprefix
; your code in intel syntax here
.att_syntax prefix
; code in at&t syntax here
如果您打算在实模式下使用它,请不要忘记切换到16位模式.code16
。
您的问题的最大问题似乎是,您不仅要尝试将代码从使用“intel-syntax”转换为使用“at& t-syntax”,而是尝试端口它到一个。另一种寻址模式和b。另一个操作系统。
特别是关于中断调用约定的问题让我想到你试图将16位DOS代码移植到在LINUX机器上运行的某种32位代码。
由于涉及不同的调用约定,只需替换数字,就不可能“重用”给定代码来执行系统调用。
您可能尝试修复代码的事项包括使用syscall read而不是BIOS中断从stdin读取
storage:
.ascii " "
# ...
movl $3, %eax # syscall number
# (check syscall.h to see if it's 3 on your system)
movl $0, %ebx # file descriptor (0 designating stdin)
movl $storage, %ecx
movl $1, %edx # number of chars to read
int $0x80
使用DOS系统调用机制int 0x21的代码必须使用类似
之类的东西来修复 movl $4, %eax # syscall number write
movl $0, %ebx # file descriptor (1 designating stdout)
movl $storage, %ecx
movl $1, %edx # number of chars to write
int $0x80
最后一步应该是修复退出系统调用:
movl $1, %eax # syscall number exit
movl $0, %ebx # it doesn't hurt to set a reasonable exit code here.
int $0x80
关于DOS系统调用,查看http://en.wikipedia.org/wiki/MS-DOS_API应该有助于了解示例代码中使用的int 0x20
和int 0x21
。
对BIOS中断进行搜索也是维基百科是你的朋友:http://en.wikipedia.org/wiki/Bios_interrupt应该回答你的问题。
在您的情况下int 0x16
0
中ah
,因此:读取字符。