【问题标题】:How to print error message using errno in assembly language如何在汇编语言中使用 errno 打印错误消息
【发布时间】:2015-05-09 11:05:25
【问题描述】:

我正在使用sys_write 系统调用以汇编语言写给stdout,如果在写入过程中发生错误,我想打印一条错误消息,然后正常退出。

使用errnoperror,我只能退出但无法打印错误消息。如果syscall 失败,如何处理错误的任何建议。我想根据发生的错误类型打印错误消息。 我在 Ubuntu 14.04 上使用 nasm 来编译我的汇编代码。 目前我只做这个:

test rax,rax    ; Lets make sure the file descriptor is valid
js  skipWrite   ;

【问题讨论】:

  • 什么架构?什么操作系统?我什至不知道汇编,但我知道没有办法用这么少的信息回答这个问题。
  • 我不了解 Ubuntu,但在 Windows 上,您必须调用操作系统的另一种方法才能获取错误代码。我想这在 Linux 上是类似的。
  • 仍然没有足够的上下文。你是怎么写文件的?提示:如果您没有使用 C 运行时库例程,因此将 C 运行时库链接到您的程序中,那么无论如何都没有 errno... 如果您使用的是直接系统调用,那么您想要的需要与使用 C 运行时不同的方法。
  • @twalberg 我已经编辑了我的问题。希望现在更清楚..

标签: linux assembly nasm x86-64


【解决方案1】:

Linux 上的系统调用接口以小的负数形式返回错误——-1 .. -4095 范围内的任何返回值(以 %rax 为单位)都是错误返回码。

所以在你的write系统调用之后,当你检查%rax的值,看看写入了多少字节,如果值为负数,则发生错误,负数为errno代码。

【讨论】:

    【解决方案2】:

    perrorerrno 仅在您链接到 libc (-lc) 时可用。

    “裸”syscall(不支持库)通常会在失败时返回“标准错误代码的负数”(man syscall(2)。使用简单的NEG,您会得到错误的正数。

    错误编号可以在 Linux 源文件 include/asm-generic/errno-base.hinclude/asm-generic/errno.h 中找到。

    手册页中描述了可能的错误,例如man open(2)。一个特定系统调用的名称可以通过here 算出来(有点想象力)。 strace 在已知有效的程序上可能会有所帮助。


    我写了一个示例,展示了如何构建带有错误消息的“Pascal”字符串列表以及如何遍历该列表:

    DEFAULT rel
    
    GLOBAL _start
    
    SECTION .data
    
        non_existing_file db "bielefeld.txt",0
    
    SECTION .text
    
    _start:
        push rbp
        mov rbp, rsp
        and rsp, -16                ; Align 16
    
        mov rdi, non_existing_file  ; Pointer to null-terminated filename
        xor rsi, rsi                ; RD_ONLY
        mov rax, 2                  ; sys_open
        syscall                     ; Call Linux
    
        ; if no errorcode (EAX > -1 || EAX < -133) exit (and close)
        cmp eax, -1
        jg .done
        cmp eax, -133
        jl .done
    
        neg rax                     ; Get positive error number: RAX = Abs (RAX)
        mov rdi, rax                ; Argument for my_perror
        call my_perror              ; Output error message
    
        .done:
        leave
        xor edi, edi                ; Return 0
        mov eax, 60                 ; sys_exit
        syscall
    
    ;==================== my_perror ====================
    
    SECTION .text
    
    my_perror:                          ; ARG: RDI=errno
        push rbp
        mov rbp, rsp
        sub rsp, 16                     ; Aligning 16 though only one byte is needed
    
        ; No processing if wrong number
        test edi, edi
        jz .done
        cmp edi, 133
        ja .done
    
        ; Walk through the err_txt-list
        xor edx,edx
        mov rsi, err_txt
        .L1:
        lea rsi, [rsi+rdx]
        mov dl, [rsi]               ; Length of string
        add rsi, 1                  ; Pointer to string
        sub edi, 1
        jnz .L1
    
        mov edi, 1                  ; stdout
        mov eax, 1                  ; sys_write
        syscall                     ; call Linux
    
        mov byte [rsp], 0x0A        ; Linefeed
        mov rsi, rsp
        mov edx, 1
        mov edi, 1                  ; stdout
        mov eax, 1                  ; sys_write
        syscall                     ; call Linux
    
        .done:
        leave
        ret
    
    SECTION .data
    
    %MACRO DATA_ERR 1
        %strlen len %1
        db len, %1
    %ENDMACRO
    
    err_txt:
    
    ; /usr/src/linux-source-3.2/include/asm-generic/errno-base.h
    DATA_ERR "Operation not permitted"                         ; EPERM             1
    DATA_ERR "No such file or directory"                       ; ENOENT            2
    DATA_ERR "No such process"                                 ; ESRCH             3
    DATA_ERR "Interrupted system call"                         ; EINTR             4
    DATA_ERR "I/O error"                                       ; EIO               5
    DATA_ERR "No such device or address"                       ; ENXIO             6
    DATA_ERR "Argument list too long"                          ; E2BIG             7
    DATA_ERR "Exec format error"                               ; ENOEXEC           8
    DATA_ERR "Bad file number"                                 ; EBADF             9
    DATA_ERR "No child processes"                              ; ECHILD           10
    DATA_ERR "Try again"                                       ; EAGAIN           11
    DATA_ERR "Out of memory"                                   ; ENOMEM           12
    DATA_ERR "Permission denied"                               ; EACCES           13
    DATA_ERR "Bad address"                                     ; EFAULT           14
    DATA_ERR "Block device required"                           ; ENOTBLK          15
    DATA_ERR "Device or resource busy"                         ; EBUSY            16
    DATA_ERR "File exists"                                     ; EEXIST           17
    DATA_ERR "Cross-device link"                               ; EXDEV            18
    DATA_ERR "No such device"                                  ; ENODEV           19
    DATA_ERR "Not a directory"                                 ; ENOTDIR          20
    DATA_ERR "Is a directory"                                  ; EISDIR           21
    DATA_ERR "Invalid argument"                                ; EINVAL           22
    DATA_ERR "File table overflow"                             ; ENFILE           23
    DATA_ERR "Too many open files"                             ; EMFILE           24
    DATA_ERR "Not a typewriter"                                ; ENOTTY           25
    DATA_ERR "Text file busy"                                  ; ETXTBSY          26
    DATA_ERR "File too large"                                  ; EFBIG            27
    DATA_ERR "No space left on device"                         ; ENOSPC           28
    DATA_ERR "Illegal seek"                                    ; ESPIPE           29
    DATA_ERR "Read-only file system"                           ; EROFS            30
    DATA_ERR "Too many links"                                  ; EMLINK           31
    DATA_ERR "Broken pipe"                                     ; EPIPE            32
    DATA_ERR "Math argument out of domain of func"             ; EDOM             33
    DATA_ERR "Math result not representable"                   ; ERANGE           34
    DATA_ERR "Resource deadlock would occur"                   ; EDEADLK          35
    
    ; /usr/src/linux-source-3.2/include/asm-generic/errno.h
    DATA_ERR "File name too long"                              ; ENAMETOOLONG     36
    DATA_ERR "No record locks available"                       ; ENOLCK           37
    DATA_ERR "Function not implemented"                        ; ENOSYS           38
    DATA_ERR "Directory not empty"                             ; ENOTEMPTY        39
    DATA_ERR "Too many symbolic links encountered"             ; ELOOP            40
    DATA_ERR "Operation would block"                           ; EWOULDBLOCK  EAGAIN
    DATA_ERR "No message of desired type"                      ; ENOMSG           42
    DATA_ERR "Identifier removed"                              ; EIDRM            43
    DATA_ERR "Channel number out of range"                     ; ECHRNG           44
    DATA_ERR "Level 2 not synchronized"                        ; EL2NSYNC         45
    DATA_ERR "Level 3 halted"                                  ; EL3HLT           46
    DATA_ERR "Level 3 reset"                                   ; EL3RST           47
    DATA_ERR "Link number out of range"                        ; ELNRNG           48
    DATA_ERR "Protocol driver not attached"                    ; EUNATCH          49
    DATA_ERR "No CSI structure available"                      ; ENOCSI           50
    DATA_ERR "Level 2 halted"                                  ; EL2HLT           51
    DATA_ERR "Invalid exchange"                                ; EBADE            52
    DATA_ERR "Invalid request descriptor"                      ; EBADR            53
    DATA_ERR "Exchange full"                                   ; EXFULL           54
    DATA_ERR "No anode"                                        ; ENOANO           55
    DATA_ERR "Invalid request code"                            ; EBADRQC          56
    DATA_ERR "Invalid slot"                                    ; EBADSLT          57
    DATA_ERR "Resource deadlock would occur"                   ; EDEADLOCK   EDEADLK
    DATA_ERR "Bad font file format"                            ; EBFONT           59
    DATA_ERR "Device not a stream"                             ; ENOSTR           60
    DATA_ERR "No data available"                               ; ENODATA          61
    DATA_ERR "Timer expired"                                   ; ETIME            62
    DATA_ERR "Out of streams resources"                        ; ENOSR            63
    DATA_ERR "Machine is not on the network"                   ; ENONET           64
    DATA_ERR "Package not installed"                           ; ENOPKG           65
    DATA_ERR "Object is remote"                                ; EREMOTE          66
    DATA_ERR "Link has been severed"                           ; ENOLINK          67
    DATA_ERR "Advertise error"                                 ; EADV             68
    DATA_ERR "Srmount error"                                   ; ESRMNT           69
    DATA_ERR "Communication error on send"                     ; ECOMM            70
    DATA_ERR "Protocol error"                                  ; EPROTO           71
    DATA_ERR "Multihop attempted"                              ; EMULTIHOP        72
    DATA_ERR "RFS specific error"                              ; EDOTDOT          73
    DATA_ERR "Not a data message"                              ; EBADMSG          74
    DATA_ERR "Value too large for defined data type"           ; EOVERFLOW        75
    DATA_ERR "Name not unique on network"                      ; ENOTUNIQ         76
    DATA_ERR "File descriptor in bad state"                    ; EBADFD           77
    DATA_ERR "Remote address changed"                          ; EREMCHG          78
    DATA_ERR "Can not access a needed shared library"          ; ELIBACC          79
    DATA_ERR "Accessing a corrupted shared library"            ; ELIBBAD          80
    DATA_ERR ".lib section in a.out corrupted"                 ; ELIBSCN          81
    DATA_ERR "Attempting to link in too many shared libraries" ; ELIBMAX          82
    DATA_ERR "Cannot exec a shared library directly"           ; ELIBEXEC         83
    DATA_ERR "Illegal byte sequence"                           ; EILSEQ           84
    DATA_ERR "Interrupted system call should be restarted"     ; ERESTART         85
    DATA_ERR "Streams pipe error"                              ; ESTRPIPE         86
    DATA_ERR "Too many users"                                  ; EUSERS           87
    DATA_ERR "Socket operation on non-socket"                  ; ENOTSOCK         88
    DATA_ERR "Destination address required"                    ; EDESTADDRREQ     89
    DATA_ERR "Message too long"                                ; EMSGSIZE         90
    DATA_ERR "Protocol wrong type for socket"                  ; EPROTOTYPE       91
    DATA_ERR "Protocol not available"                          ; ENOPROTOOPT      92
    DATA_ERR "Protocol not supported"                          ; EPROTONOSUPPORT  93
    DATA_ERR "Socket type not supported"                       ; ESOCKTNOSUPPORT  94
    DATA_ERR "Operation not supported on transport endpoint"   ; EOPNOTSUPP       95
    DATA_ERR "Protocol family not supported"                   ; EPFNOSUPPORT     96
    DATA_ERR "Address family not supported by protocol"        ; EAFNOSUPPORT     97
    DATA_ERR "Address already in use"                          ; EADDRINUSE       98
    DATA_ERR "Cannot assign requested address"                 ; EADDRNOTAVAIL    99
    DATA_ERR "Network is down"                                 ; ENETDOWN        100
    DATA_ERR "Network is unreachable"                          ; ENETUNREACH     101
    DATA_ERR "Network dropped connection because of reset"     ; ENETRESET       102
    DATA_ERR "Software caused connection abort"                ; ECONNABORTED    103
    DATA_ERR "Connection reset by peer"                        ; ECONNRESET      104
    DATA_ERR "No buffer space available"                       ; ENOBUFS         105
    DATA_ERR "Transport endpoint is already connected"         ; EISCONN         106
    DATA_ERR "Transport endpoint is not connected"             ; ENOTCONN        107
    DATA_ERR "Cannot send after transport endpoint shutdown"   ; ESHUTDOWN       108
    DATA_ERR "Too many references: cannot splice"              ; ETOOMANYREFS    109
    DATA_ERR "Connection timed out"                            ; ETIMEDOUT       110
    DATA_ERR "Connection refused"                              ; ECONNREFUSED    111
    DATA_ERR "Host is down"                                    ; EHOSTDOWN       112
    DATA_ERR "No route to host"                                ; EHOSTUNREACH    113
    DATA_ERR "Operation already in progress"                   ; EALREADY        114
    DATA_ERR "Operation now in progress"                       ; EINPROGRESS     115
    DATA_ERR "Stale NFS file handle"                           ; ESTALE          116
    DATA_ERR "Structure needs cleaning"                        ; EUCLEAN         117
    DATA_ERR "Not a XENIX named type file"                     ; ENOTNAM         118
    DATA_ERR "No XENIX semaphores available"                   ; ENAVAIL         119
    DATA_ERR "Is a named type file"                            ; EISNAM          120
    DATA_ERR "Remote I/O error"                                ; EREMOTEIO       121
    DATA_ERR "Quota exceeded"                                  ; EDQUOT          122
    DATA_ERR "No medium found"                                 ; ENOMEDIUM       123
    DATA_ERR "Wrong medium type"                               ; EMEDIUMTYPE     124
    DATA_ERR "Operation Canceled"                              ; ECANCELED       125
    DATA_ERR "Required key not available"                      ; ENOKEY          126
    DATA_ERR "Key has expired"                                 ; EKEYEXPIRED     127
    DATA_ERR "Key has been revoked"                            ; EKEYREVOKED     128
    DATA_ERR "Key was rejected by service"                     ; EKEYREJECTED    129
    DATA_ERR "Owner died"                                      ; EOWNERDEAD      130
    DATA_ERR "State not recoverable"                           ; ENOTRECOVERABLE 131
    DATA_ERR "Operation not possible due to RF-kill"           ; ERFKILL         132
    DATA_ERR "Memory page has hardware error"                  ; EHWPOISON       133
    

    【讨论】:

    • lea rsi, [rsi+rdx] 可能只是 add rsi, rdx。您可以改用esixor rsi, rsi 中保存一个字节,而mov rax, 2 应该使用eax(NASM 确实优化了这种情况,但 YASM 没有。)此外,syscall 仅破坏rcxr11,所以你可以注释掉第二个mov edi, 1。 (对于stderr,实际上应该是2。如果write 到stdout 失败,OP 想要打印一个错误,所以它也可能会因为你的错误而失败。
    猜你喜欢
    • 2022-10-18
    • 1970-01-01
    • 2017-03-01
    • 2017-03-19
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    相关资源
    最近更新 更多