【问题标题】:Porting 16-bit DOS x86 assembly to 32-bit Linux x86 assembly将 16 位 DOS x86 程序集移植到 32 位 Linux x86 程序集
【发布时间】:2013-03-24 10:05:30
【问题描述】:

我在 80836 DOS 程序集中找到了我想使用 AT&T 语法移植到 32 位 Linux 程序集的代码。

我发现网站解释了一些差异,但仅与寄存器有关。例如:

  1. cmp al, 'A' -> cmp 'A', %al

所以我在转换以下代码时遇到了问题:

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

我认为:

  1. sub al, 57h ---> sub $0x57, %al 和 ETC(不确定)

最糟糕的问题是中断,因为在 AT&T 汇编中它就像:

SYSCALL = 0X80
SYSEXIT = 1
EXIT_SUCCESS = 0
SYSREAD = 3
SYSWRITE = 4
STDIN = 0
STDOUT = 1  

在 DOS16 中,16h? 20 小时? 21 小时?哦,伙计,即使这样 int 20h 也充当中断和值(mov dl,20h)?如此混乱。

有人可以帮我吗?

@编辑 我像这样转换它,但出现分段错误错误。我几乎可以肯定这是关于中断..

.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

有人吗?

【问题讨论】:

  • 如果您只想将 16 位 Intel 汇编语法转换为 16 位 AT&T 汇编语法,int 21h 将变为 int $0x21。你所说的“AT&T 程序集”是 Linux 32 位系统调用的一些功能。我很确定没有从 16 位 DOS 程序集到 32 位 Linux 程序集的转换器。为此,您需要学习 Linux 32 位汇编。您还在阅读带有 BIOS 键盘中断int 16h 的键盘。在 Linux 中,您需要为此使用 Linux 系统调用 (int 0x80)。那么,你的目标是什么? 1. 仅将语法从 Intel 转换为 AT&T(不移植到 Linux),或 2. 将 DOS 代码移植到 Linux。
  • 当然是使用 linux 系统调用的端口!我希望这是 ubuntu 中的工作程序。我更改了出口,很容易将 $1 更改为 %eax 和 int 0x80,但我在它之前的行(mov dl,20h int 21h)和 intput 遇到了大问题。我不知道如何将其更改为工作代码

标签: linux assembly x86 dos att


【解决方案1】:

小问题

您的代码“转换”的主要问题可能是您似乎将一些想法与并不真正适用的术语“80836 程序集”和“at&t”联系起来。

虽然这可能只是命名约定的问题,但没有“80386 程序集”与“at&t”的区别,而是“intel”与“at&T 语法”的区别,因为 both 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 位代码。

仅通过简单地替换数字来“重用”给定代码来执行系统调用是不可能的,因为这涉及到不同的调用约定。

您可能会尝试修复代码的方法包括使用系统调用读取而不是 BIOS 中断来从标准输入读取数据

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

请求的文档来源

【讨论】:

  • 你能解释一下 intput 是做什么的吗? input: mov ah, 00h int 16h cmp ah, 1ch 以及键盘上的“intput”到底在哪里?以及“退出”之前的最后一行2?我会更容易转换知道该做什么.. je exit
  • 作为对您的反馈的回应,我更新了帖子以包含请求的参考资料。最好去那里看看。
猜你喜欢
  • 1970-01-01
  • 2019-01-12
  • 2011-04-03
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多