组装:分段故障原因

Assembly: cause of segmentation fault

提问人:cMard 提问时间:11/18/2023 更新时间:11/18/2023 访问量:48

问:

我是新手,所以我没有那么多知识。我只是想从用户那里读取一些,然后输出,然后输出用户输入的内容。assembly languagemessage"Hello, World!\n"message

这是我基本上要做的:


# TODO: Read message from input, output "Hello, World!", and output message on newline 

.section .data                  # Data that will be used by program


  ## * CONSTANTS * ##

  .equ LINUX_SYSCALL, 0x80      # Interrupt ID to make syscall on kernel (GNU/Linux)
  
  ## * SYCALL IDs * ##
  .equ EXIT_SYS, 1              # SYSCALL Number for exiting
  .equ OPEN_SYS, 5              # SYSCALL Number for opening files
  .equ READ_SYS, 3              # SYSCALL Number for reading from files
  .equ WRITE_SYS, 4             # SYSCALL Number for writing to files
  .equ CLOSE, 6                 # SYSCALL Number to close files

  ## * File modes * ##
  .equ READ_MODE, 0              # Reading mode for files
  .equ WRITE_MODE, 03101         # Writing mode for files

  ## * File permissions * ##
  .equ DEFAULT_PERMISSION, 0666  # Default permission to interact with files

  ## * Default file descriptors * ##
  
  .equ STDIN, 0                  # Default GNU/Linux input file
  .equ STDOUT, 1                 # Default GNU/Linux output file
  .equ STDERR, 2                 # Default GNU/Linux error-log file

  ## * Constant variables * ##

  OUTPUT_MSG:                   # "Hello, World!" message
    .ascii "Hello, World!\n"

  SIZE_OF_MSG:                  # Size of "Hello, World!"
    .long 14                    # remember to count '\n' as 1 byte

.section .bss                   # Reserved memory area
  .equ BUFFER_SIZE, 500         # Size of buffer that will be read from STDIN
  .lcomm BUFFER, 500            # Buffer that will be read from STDIN
  

.section .text                  # Code area
.globl _start                   # Starting function definiton



# @brief: Label to terminate program successfuly
_exit_success:
  movl $EXIT_SYS, %eax          
  movl $0, %ebx
  int $LINUX_SYSCALL

# @brief: Label to output `message` that stored in `%ecx`
# @param: `%ecx` must have `message` to output
# @param: `%edx` must have size of `message`
_output_msg:
  movl $WRITE_SYS, %eax
  movl $STDOUT, %ebx
  int $LINUX_SYSCALL
  ret

# @brief: Label to get input `buffer` from STDIN
# @param: `%ecx` must have `buffer` to store data
# @param: `%edx` must have size of `buffer` which will be used for data
_read_msg:
  movl $READ_SYS, %eax
  movl $STDIN, %ebx
  int $LINUX_SYSCALL
  ret


# @brief: Label to get size of a `buffer`
# @param: `%eax` must have pointer to `buffer`'s first char
# @return: size of buffer will be stored in `%edx`
_get_buffer_size:
  movl $0, %edx
  jmp .start_buffer_size
  ret

.start_buffer_size:
  incl %eax
  incl %edx
  cmpl $0, (%eax)   
  jnz .start_buffer_size
  ret

# @brief: _start function to start program
_start:

  ## * Get input message * ##
  movl $BUFFER, %ecx
  movl $BUFFER_SIZE, %edx
  call _read_msg

 
  ## * Output constant message * ##
  movl $OUTPUT_MSG, %ecx        # Store message in %ecx parameter
  movl $SIZE_OF_MSG, %edx       # Store size of message in %edx parameter
  call _output_msg              # Output the constant message

  ## * Output message that was read * ##
  movl $BUFFER, %ecx
  call _get_buffer_size 
  call _output_msg

  jmp _exit_success             # Terminate program

_exit_success:

这个只是终止程序。是 1,并且是 。EXITSYSLINUX_SYSCALL0x80

_output_msg:

此标签输出存储在 中的消息,其大小必须在寄存器上。这里是 4 和 1%ecx%edxWRITE_SYSSTDOUT

_read_msg:

此标签从(即 0)获取输入。必须存储在 并且保留的大小必须为 onSTDINBUFFER%ecxBUFFER%edx

_get_buffer_size:

这里必须是 的第一个字符,输出 (大小 ) 将开启%eaxBUFFERBUFFER%edx

我知道不是这样使用的,但是with的方法对我来说很复杂,所以我尝试了自己的方法(是的,它只是存储和in)。functionsassemblystackparametersreturn valueregisters

我认为问题出在,因为错误表明程序访问(或尝试访问)不存在或不允许我们访问(或尝试访问)的内存地址。_get_buffer_sizesegmentation fault

程序集 x86 分段错误

评论

3赞 Peter Cordes 11/18/2023
应该是像但在 4 字节块中?或者你的意思是单独检查每个字节而不是?你先递增,这样它就不会检查第一个字节。此外,其调用方在 ECX 中传递指针,但它需要 EAX 中的指针。所以这就是它段错误的原因;GDB 应该显示它。但实际上,保存 ;除非您正在搜索第一个或最后一个换行符或其他内容,否则无需遍历数据。 不以缓冲区零结尾,读/写使用指针+长度缓冲区而不是 C 字符串。_get_buffer_sizestrlencmpbcmplreadread
0赞 cMard 11/18/2023
@PeterCordes谢谢!我实际上忘记了读取系统调用返回消息大小。

答: 暂无答案