将16位DOS x86程序集移植到32位Linux x86程序集 [英] Porting 16-bit DOS x86 assembly to 32-bit Linux x86 assembly

查看:73
本文介绍了将16位DOS x86程序集移植到32位Linux x86程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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:

  1. 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

我正在转换我认为:

  1. 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 and int 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 with 0 in ah - thus: read character.

      这篇关于将16位DOS x86程序集移植到32位Linux x86程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆