x86 ASM 代码不打印所需的数字输出,仅打印消息

问题描述 投票:0回答:1

我试图找到给定三个数字的最小和最大数字。

这是我目前的代码:

    section .text
       global _start         ;must be declared for using gcc
    
    _start:                   ;tell linker entry point
       mov   ecx, [num1]
       mov   ebx, ecx         ; initialize ebx with num1 (smallest so far)
       cmp   ecx, [num2]
       jl    check_third_num  ; jump if num1 < num2
       mov   ecx, [num2]
       mov   ebx, ecx         ; update ebx if num2 is smaller
       
    check_third_num:
       cmp   ecx, [num3]
       jl    update_smallest  ; jump if num2/num1 < num3
       mov   ecx, [num3]
       
    update_smallest:
       mov   [smallest], ecx  ; store the smallest number found
    
       mov   ecx, [num1]
       cmp   ecx, [num2]
       jg    check_largest    ; jump if num1 > num2
       mov   ecx, [num2]
       
    check_largest:
       cmp   ecx, [num3]
       jg    print_result     ; jump if num2/num1 > num3
       mov   ecx, [num3]
    
    print_result:
       mov   [largest], ecx   ; store the largest number found
       
       ; Print the largest number
       mov   ecx, msg_largest
       mov   edx, len_largest
       mov   eax, 4            ; system call number (sys_write)
       mov   ebx, 1            ; file descriptor (stdout)
       int   0x80              ; call kernel
    
       ; Print the smallest number
       mov   ecx, msg_smallest
       mov   edx, len_smallest
       mov   eax, 4            ; system call number (sys_write)
       mov   ebx, 1            ; file descriptor (stdout)
       int   0x80              ; call kernel
    
       mov   eax, 1
       int   80h               ; exit
    
    section .data
       msg_largest db "The largest digit is: ", 0xA, 0xD 
       len_largest equ $ - msg_largest
       msg_smallest db "The smallest digit is: ", 0xA, 0xD 
       len_smallest equ $ - msg_smallest
       num1 dd '47'
       num2 dd '22'
       num3 dd '31'
     
    section .bss
       largest resb 2
       smallest resb 2

我很困惑似乎是什么问题。是在

update_smallest
代码上,还是按照我在
section .data
上声明的方式?我尝试对其进行调整,首先将其转换为 ASCII,但这让我有点困惑,所以我尝试按照我拥有的 pdf 文件中的内容进行操作。我只是尝试模仿它的结构,但是现在我添加了查找最小数字的算法,代码不会打印最小和最低的数字。这就是我试图调整的:

    section .text
       global _start         ;must be declared for using gcc
    
    _start:                   ;tell linker entry point
       mov   ecx, [num1]
       mov   ebx, ecx         ; initialize ebx with num1 (smallest so far)
       cmp   ecx, [num2]
       jl    check_third_num  ; jump if num1 < num2
       mov   ecx, [num2]
       mov   ebx, ecx         ; update ebx if num2 is smaller
       
    check_third_num:
       cmp   ecx, [num3]
       jl    update_smallest  ; jump if num2/num1 < num3
       mov   ecx, [num3]
       
    update_smallest:
       mov   [smallest], ecx  ; store the smallest number found
    
       mov   ecx, [num1]
       cmp   ecx, [num2]
       jg    check_largest    ; jump if num1 > num2
       mov   ecx, [num2]
       
    check_largest:
       cmp   ecx, [num3]
       jg    print_result     ; jump if num2/num1 > num3
       mov   ecx, [num3]
    
    print_result:
       mov   [largest], ecx   ; store the largest number found
       
       ; Print the largest number
       mov   ecx, msg_largest
       mov   edx, len_largest
       mov   eax, 4            ; system call number (sys_write)
       mov   ebx, 1            ; file descriptor (stdout)
       int   0x80              ; call kernel
    
       ; Print the smallest number
       mov   ecx, msg_smallest
       mov   edx, len_smallest
       mov   eax, 4            ; system call number (sys_write)
       mov   ebx, 1            ; file descriptor (stdout)
       int   0x80              ; call kernel
    
       mov   eax, 1
       int   80h               ; exit
    
    section .data
       msg_largest db "The largest digit is: ", 0xA, 0xD 
       len_largest equ $ - msg_largest
       msg_smallest db "The smallest digit is: ", 0xA, 0xD 
       len_smallest equ $ - msg_smallest
       num1 dd '47'
       num2 dd '22'
       num3 dd '31'
     
    section .bss
       largest resb 2
       smallest resb 2

我的第一个代码中似乎有什么问题?

assembly printing x86 output
1个回答
2
投票
  • 考虑到源代码注释,您似乎不理解以下内容: 指令

    db
    dd
    等以升序文本顺序将数据存储到内存中。 稍后数据出现在更高地址。 这意味着
    num1
    的存储方式如下:

    内存地址 记忆内容 评论
    num1 + 0
    0x34
    '4'
    num1 + 1
    0x37
    '7'
    num1 + 2
    0x00
    NUL 填充以占据
    dword
    num1 + 3
    0x00

    现在,当您从

    dword
    加载带有
    mov
    num1
    时,ecx 寄存器的
    最低有效字节
    映射到最小内存地址处的字节(反之亦然)。 这意味着当您比较
    dd '47'
    dd '31'
    时,您实际上是在比较数字
    0x00003734
    0x00003133
    。 该方案称为 little Endian

  • 作为中间步骤,我建议您进行 Three

    sys_write
    系统调用。 一种用于消息前缀,一种用于实际数字字符串,另一种用于尾随换行符。

  • 如果按预期工作(=正确的结果),您可以增加复杂性: 你可以这样预留一些空间

    section .data
    msg_largest:
        db 'The largest number is: '
    msg_largest_num:
        db '  '
        db 0x0A
    len_largest equ $ - msg_largest
    

    并将“最大”数字串放在

    msg_largest_num
    处。 确保仅覆盖两个空白字节。

  • 字符序列 LF+CR (

    0x0A, 0x0D
    ) 非常不寻常: 滑架返回左侧页边距的行程时间比换行前进的时间要长,因此它始终是 CR+LF,反之亦然。

    但是,显然您是为 32 位 Linux 或兼容的 ABI 编程。 在类 UNIX 环境中,只需简单的 LF 就足够了,请参阅维基百科上的“换行符” 了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.