将16位DOS x86程序集移植到32位Linux x86程序集 [英] Porting 16-bit DOS x86 assembly to 32-bit Linux x86 assembly
问题描述
我在80836 DOS程序集中找到了我想使用AT& T语法移植到32位Linux程序集的代码.
I found code in 80836 DOS assembly that I'd like to port to 32-bit Linux assembly, using AT&T syntax.
我发现了一个网站,该网站解释了一些差异,但仅与寄存器有关.例如:
I found site that explains some differences but only about registers. EX:
- cmp al,'A'-> cmp'A',%al
因此我在转换以下代码时遇到问题:
So I got problems converting following code:
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
我正在转换我认为:
- sub al,57h ---> sub $ 0x57,%al和ETC(不确定)
最糟糕的问题是中断,因为在AT& T汇编中,就像:
The worst problem is with interrupts since in AT&T assembly it's like:
SYSCALL = 0X80
SYSEXIT = 1
EXIT_SUCCESS = 0
SYSREAD = 3
SYSWRITE = 4
STDIN = 0
STDOUT = 1
在DOS16中16h?20小时?21小时?哦,伙计,甚至int 20h仍然充当中断和值(mov dl,20h)?如此混乱.
And in DOS16, 16h? 20h? 21h? oh man, and even then int 20h acts as interrupt and as value (mov dl, 20h)? so confusing.
有人可以帮我吗?
@EDIT我像这样转换它,但是出现了段错误错误.我几乎可以肯定这是关于中断的.
@EDIT I converted it like this, but I got segmentation fault error. I am almost sure it's about interrupts..
.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
有人吗?
推荐答案
次要问题
代码转换"的主要问题可能是您似乎将一些概念与"80836汇编"和"at& t"这两个词并没有真正应用.
Minor Problem
Probably the main problem of your code "conversion" is that you seem to connect some ideas with the terms "80836 assembly" and "at&t" that don't really apply.
尽管这可能只是命名约定的问题,但"strong"和"at& t语法"之间并没有"80386程序集"与"at& T语法"的区别,两者都是两者可以使用intel语法和at& t语法来描述x86汇编代码.
Although this might just be a matter of naming conventions there is no "80386 assembly" vs. "at&t" difference but a "intel" vs. "at&T syntax" difference as both intel syntax and at&t syntax can be used to describe x86 assembly code.
如果您使用的是GNU汇编器(我不知道其他使用AT& T语法而不是intel的x86汇编器),您可能只想使用 .intel_syntax
并保持使用的intel语法而是在您的参考资料中.
If you are using GNU assembler (I don't know any other x86 assembler using AT&T syntax instead of intel) you might just want to use .intel_syntax
and stay with the intel syntax used in your reference material instead.
.intel_syntax noprefix
; your code in intel syntax here
.att_syntax prefix
; code in at&t syntax here
如果要在实模式下使用它,请不要忘记切换到16位模式. .code16
.
Don't forget to switch to 16-bit mode.code16
if you intend to use it in real mode.
这个问题更大的问题似乎是,您不仅在尝试将代码从[in-syntax]转换为[at& t-syntax],而且要转换端口它到一个.另一个寻址模式和b.另一个操作系统.
The far the bigger problem with your question seems to be that you are not only trying to transform the code from using "intel-syntax" to using "at&t-syntax" but rather to port it to a. another addressing mode and b. another operating system.
尤其是您有关中断调用约定的问题使我想到一个假设,您正在尝试将16位DOS代码移植到在LINUX机器上运行的某种32位代码上.
Especially your question about interrupt calling conventions leads me to the assumption you are trying to port 16-bit DOS code to some kind of 32-bit code running on a LINUX machine.
仅通过替换数字就不可能重用"给定的代码来执行系统调用,因为其中涉及不同的调用约定.
Just "reusing" the given code to perform system calls won't be possible by simply replacing numbers as there a different calling conventions involved.
您可能会尝试修改代码的方法包括使用syscall read而不是BIOS中断来从stdin读取
Things you might try to fix your code include using syscall read instead of BIOS interrupt to read from 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 syscall机制int 0x21的代码
Code utilizing DOS syscall mechanism int 0x21 would have to be fixed in addition using something like
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
最后一步应该是修复出口syscall:
The last step should be fixing the exit syscall:
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
.Requested Documentation Source
Regarding DOS syscalls taking a look at http://en.wikipedia.org/wiki/MS-DOS_API should help to understand what
int 0x20
andint 0x21
are used for in your example code.为BIOS中断而抢劫也是Wikipedia的朋友: http://en.wikipedia.org/wiki/Bios_interrupt 应该回答您的问题.
Seraching for BIOS interrupt also wikipedia is your friend: http://en.wikipedia.org/wiki/Bios_interrupt should answer your question.
在您的情况下,它是
int 0x16
和ah
中的0
-因此:读取字符.in your case it is
int 0x16
with0
inah
- thus: read character.这篇关于将16位DOS x86程序集移植到32位Linux x86程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!