将16位DOS x86程序集移植到32位Linux x86程序集

时间:2013-03-24 10:05:31

标签: linux assembly x86 dos att

我在80836 DOS程序集中找到了代码,我希望使用AT& T语法将其移植到32位Linux程序集。

我发现网站解释了一些差异,但只是关于寄存器。 EX:

  1. cmp al,'A' - > cmp'A',%al
  2. 所以我在转换以下代码时遇到了问题:

    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(不确定)
    2. 最糟糕的问题是中断,因为在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
      

      任何?

1 个答案:

答案 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

请求的文档来源