x64 NASM Assembly 打印从函数返回的单个字符。

huangapple go评论106阅读模式
英文:

x64 NASM Assembly print a single character returned from the function

问题

I noticed some issues in your NASM x64 Assembly code that may be causing the problem with not displaying the expected result. Here's the corrected code:

  1. ; NASM x64 Assembly program to add two numbers and print the result
  2. section .data
  3. message db "The sum is: ", 0 ; Null-terminated string
  4. section .bss
  5. result resb 1 ; Reserve space for a single byte (to store the result)
  6. section .text
  7. global _start
  8. _start:
  9. ; Display the message
  10. mov rax, 0x1 ; Syscall number for sys_write (1)
  11. mov rdi, 0x1 ; File descriptor for STDOUT (1)
  12. mov rsi, message ; Pointer to the message
  13. mov rdx, 13 ; Message length
  14. syscall
  15. ; Calculate the sum (4 + 5)
  16. mov rax, 4
  17. add rax, 5
  18. mov [result], al ; Store the result in the result variable
  19. ; Display the result
  20. mov rax, 0x1 ; Syscall number for sys_write (1)
  21. mov rdi, 0x1 ; File descriptor for STDOUT (1)
  22. mov rsi, result ; Pointer to the result
  23. mov rdx, 1 ; Result length (1 byte)
  24. syscall
  25. ; Exit the program
  26. mov rax, 60 ; Syscall number for sys_exit (60)
  27. xor rdi, rdi ; Exit status (0)
  28. syscall

In this corrected code:

  1. I removed unnecessary procedure calls and the _sum function, as it was not needed for adding two numbers.

  2. I used the resb directive to reserve space for a single byte to store the result, and then I stored the result in that memory location using mov [result], al.

  3. I ensured that the message string is null-terminated by adding a null character (0) at the end of the string.

  4. I made sure to set the correct message length when calling the write syscall (13 characters).

  5. Finally, I used the correct syscall number (60) and exit status (0) when exiting the program.

Please try assembling and running this corrected code, and it should display the expected result: "The sum is: 9".

英文:

I was writing a simple NASM x64 Assembly program that adds two single-digit numbers(4 and 5 respectively) and print it on the screen. However, I wanted to use a procedure call(function). So I designed the the program in C language first.

  1. #include <stdio.h>
  2. int sum(int x, int y) {
  3. int result = x + y;
  4. return result;
  5. }
  6. int main(void) {
  7. int x = 4;
  8. int y = 5;
  9. int result = sum(x, y);
  10. printf("The sum is: %d\n", result);
  11. return 0;
  12. }

And I rewrote the program in NASM x64 Assembly program like below. The expected output from the program was The sum is: 9. However, I only could see the result except for the calculation result, just The sum is: .

  1. ; Nasm 2.15.05 (on Linux x64)
  2. STDOUT equ 0x01 ; for RDI (file descriptor)
  3. WRITE equ 0x01 ; for RAX (for syscall itself)
  4. section .data
  5. message db "The sum is: "
  6. messageLength equ $ - message
  7. section .text
  8. global _start
  9. _start:
  10. mov rax, WRITE
  11. mov rdi, STDOUT
  12. mov rsi, message
  13. mov rdx, messageLength
  14. syscall
  15. mov rdi, 0x4
  16. mov rsi, 0x5
  17. call _sum
  18. mov rcx, rax ; The result of the _sum (stored in RAX register)
  19. mov rax, WRITE
  20. mov rdi, STDOUT
  21. mov rsi, rcx
  22. mov rdx, 0x01
  23. syscall
  24. ; exit
  25. mov rax, 0x3C
  26. mov rdi, 0x00
  27. syscall
  28. _sum:
  29. mov rax, rdi
  30. add rax, rsi
  31. add rax, '0' ; To make it printable ASCII
  32. ret ; Result: 0x39 (A single character '9' in ASCII)

(My environment is WSL Ubuntu 22.04 on Windows 11, Intel i9-13900H CPU)

  1. knightchaser@3rdfr13nds:~/assembly$ ./procedures_x64
  2. The sum is: knightchaser@3rdfr13nds:~/assembly$

With GDB(GNU Debugger), I checked the calculation of _sum was successful so 0x39(9 in ASCII character) was stored in RAX register and the program doesn't show any explicit errors like segmentation fault.

I used the following commands to make the executable program.

  1. nasm -f elf64 -o procedures_x64.o procedures_x64.asm
  2. ld -o procedures_x64 procedures_x64.o

But I can't see the result. Are there wrong points in my Assembly code? Thanks in advance!

答案1

得分: 2

为了打印您的字符,您需要执行以下操作:

  1. mov rcx, rax ; _sum 的结果(存储在 RAX 寄存器中)
  2. ;...
  3. mov rsi, rcx

问题在于rax中返回的值是一个单个字符,并且您将这个单个字符的移动到rsi中。write系统调用期望rsi中的值是指向字符的指针,而不是实际的字符值本身。

您需要将字符存储在内存中,然后将指向该内存的指针传递给write函数。

如果您在C中编写了一个精确等效的代码,那么当您需要使用指针操作符&来打印返回的字符(或使用字符数组)时,这将非常明显。我强烈建议您先使正确的C程序运行起来,包括系统调用、适当的sum函数以及从int到字符串的转换,并将其用作汇编程序的蓝图。

英文:

To print your character you do

  1. mov rcx, rax ; The result of the _sum (stored in RAX register)
  2. ;...
  3. mov rsi, rcx

The problem is that the value returned in rax is a single character, and you move that single character value into rsi. The write system call expects the value in rsi to be a pointer to a character, not the actual character value itself.

You need to store the character in memory, and then pass a pointer to that memory to the write function.

If you wrote an exact equivalent in C it would be very obvious when you have to use the pointer-to operator & to print the returned character (or used a character array). I highly recommend that you get the proper C Program working, with the system calls and a proper sum function and conversion from int to a string, and use that as the blueprint for the assembly program.

huangapple
  • 本文由 发表于 2023年7月10日 13:48:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76650936.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定