当前位置: 首页 > 面试题库 >

使用x86 32位Linux sys_write(NASM)打印整数

施令秋
2023-03-14
问题内容

我是这个论坛的新手。我对高级语言有一点经验(很少)。将近一个月前,我认为查看汇编的工作方式是一个好主意,因此在Linux上选择nasm(IA-32)之后,我开始从教程中学习。

现在,结束它之后,我尝试编写一个简单的程序,在该程序中,您可以让计算机打印一个包含100个数字的列表(1 2 4 8 16
…),但是我什至无法正确显示它。我得到以下输出:

1PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP(continues)...

程序是这样的:

section .text
    global main
main:
    mov word [num], '1'
    mov ecx, 100
doubl:
    push ecx ; to push the loop counter

    mov eax, 4
    mov ebx, 1
    mov ecx, num
    mov edx, 1
    int 0x80

    sub ecx, 30h
    add ecx, ecx   ; shl ecx, 1
    add ecx, 30h
    mov [num], ecx   ; deleting this line I get  11111111111111111...

    pop ecx  ; to pop the loop counter
    loop doubl
exit:
    mov eax, 1
    int 0x80    
section .bss
num resw 2

看起来错误在于将数字加倍的部分或将其存储在变量“ num”中的部分,但我不知道为什么会发生以及如何解决。

顺便说一句,有人可以向我解释何时确切使用方括号?有规则吗?本教程将其称为“有效地址”,当我想移动变量的内容(或对其进行某些处理)而不是将其移至变量的地址时,似乎必须使用方括号。但是我对此很困惑。我看到它用在:

mov ebx, count
inc word [ebx]
mov esi, value
dec byte [esi]

但是人们是否想增加寄存器的内容不是很明显(因为它没有地址(或者没有地址吗?)?


问题答案:

您的数字将迅速增长,而不仅仅是一个数字。您应该做的是输入一个整数num而不是一个字符,然后将该整数转换为可以使用打印的字符串sys_write

这是进行转换的一种方法:重复除以10,首先获得最低的位数作为余数:

; Input:
; eax = integer value to convert
; esi = pointer to buffer to store the string in (must have room for at least 10 bytes)
; Output:
; eax = pointer to the first character of the generated string
; ecx = length of the generated string
int_to_string:
  add esi,9
  mov byte [esi],0    ; String terminator

  mov ebx,10
.next_digit:
  xor edx,edx         ; Clear edx prior to dividing edx:eax by ebx
  div ebx             ; eax /= 10
  add dl,'0'          ; Convert the remainder to ASCII 
  dec esi             ; store characters in reverse order
  mov [esi],dl
  test eax,eax            
  jnz .next_digit     ; Repeat until eax==0

  ; return a pointer to the first digit (not necessarily the start of the provided buffer)
  mov eax,esi
  ret

您可以这样使用:

    mov    dword [num],1
    ...
    mov    eax,[num]       ; function args using our own private calling convention
    mov    esi,buffer
    call   int_to_string
; eax now holds the address that you pass to sys_write
    ...

section .bss
    num    resd 1
    buffer resb 10

您的倍数可以简化为shl dword [num],1。或者更好的是,在仍与保持一致时,将其加倍add eax,eax



 类似资料:
  • 问题内容: 在我的代码中,我使用整数乘以100作为小数(0.1为10等)。您能帮我格式化输出以显示为十进制吗? 问题答案:

  • 问题内容: 假设我在寄存器中有一个整数,该如何打印?您可以显示一个简单的示例代码吗? 我已经知道如何打印一个字符串,例如“ hello,world”。 我正在Linux上进行开发。 问题答案: 如果您已经在Linux上,则无需自己进行转换。只需使用printf即可: 请注意,由于使用了cdecl调用约定,因此我们需要在此之后恢复堆栈指针,即,将每个传递给函数的参数添加4个字节。

  • 问题内容: 我正在尝试使用面向x86 GNU / Linux体系结构的 NASM 打印单个字符或数字。 这是我正在使用的代码: 但是,运行此代码不会打印任何内容。我究竟做错了什么? 问题答案: 应该包含一个指向char缓冲区开始的指针。因此,您必须将缓冲区存储在内存中。您可以执行以下操作: 您可以或其他任何地址(如果可以的话)覆盖堆栈中的所有内容。 或者,您可以使用一个字符数组来代替即时存储。 制

  • 我有一个连接到CUPS的打印机,它支持双面打印,如何通过java例程将其设置为单面打印或双面打印? 我曾尝试使用它的库使用ASET添加和addViewer首选项没有任何运气。 有人能提供一些建议吗?

  • 我目前的工作是创建机械图纸,用于发送给客户和作为施工图。当我的绘图完成后,我导出一个. pdf文件,并将其发送给客户端。 我们的客户非常喜欢黑白画,所以我试着提供他们。但是我用来画画的软件效果不好。它只有一个选项“所有颜色都是黑色”,我的画上有一些白色的“隐藏线”。当然,这些显示使用所有颜色作为黑色选项。 我找到了一个解决方案,那就是使用pdf打印机。效果很好,效果也很好。 现在我想打印这个。pd

  • 为了处理文字和图形而使用视讯显示器时,设备无关的概念看来非常完美,但对于打印机,设备无关的概念又怎样呢? 总的说来,效果也很好。在Windows程序中,用于视讯显示器的GDI函数一样可以在印表纸上打印文字和图形,在以前讨论的与设备无关的许多问题(多数都与平面显示的尺寸、分辨率以及颜色数有关)都可以用相同的方法解决。当然,一台打印机不像使用阴极射线管的显示器那么简单,它们使用的是印表纸。它们之间有一