本文介绍了使用x86 32位Linux sys_write(NASM)打印整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new to this forum.I have a little experience with high-level languages (really little). Nearly one month ago I thought it would be a good idea to see how assembly worked so after choosing nasm (IA-32) on linux I started learning from a tutorial.

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

Now, after ending it, I tried to write a simple program where you get the computer to print a list of 100 number (1 2 4 8 16...) but I couldn't even get it right.I get this output:

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"中的那一部分,但我不明白为什么会发生这种情况以及如何解决它.

It looks like the error is in the part that doubles the number or the one that stores it in the variable 'num', yet I don't understand why it happens and how to solve it.

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

By the way can someone explain me when to use the square brackets exactly? Is there a rule or something? The tutorial calls it "effective address" and it looks like I have to use the brackets when I want to move (or do something with) the content of a variable instead of doing it to the variable's address. Yet I'm quite confused about it. I see it used in:

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

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

But isn't it obvious that one wants to increment the content of the register (since it doesn't have an address (or does it?) ??

推荐答案

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

Your numbers will quickly grow larger than just a single digit. What you ought to be doing is have an integer in num rather than a character, and then convert that integer into a string that you can print with sys_write.

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

Here's one way of doing the conversion: repeated division by 10, getting the lowest digit first as the remainder:

; 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寄存器中的某个时候将其加倍.

Your number-doubling can be simplified to shl dword [num],1. Or better, double it at some point while it's still in a register with add eax,eax.

这篇关于使用x86 32位Linux sys_write(NASM)打印整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 10:40