linux - 在环境变量后查找空指针

标签 linux assembly x86

我正在读一本书(Jeff Duntemann 的《一步步汇编语言,Linux 编程》),我正在尝试更改这个显示参数的程序,改为显示环境变量。我试图只使用到目前为止所教的内容(没有C),并且我已经得到了打印环境变量的程序,但只有在我计算了我有多少个环境变量并使用了立即数之后,显然不令人满意。这是我所拥有的:

global  _start          ; Linker needs this to find the entry point!

_start:
    nop         ; This no-op keeps gdb happy...

    mov ebp,esp     ; Save the initial stack pointer in EBP
; Copy the command line argument count from the stack and validate it:
    cmp dword [ebp],MAXARGS ; See if the arg count exceeds MAXARGS
    ja Error        ; If so, exit with an error message

; Here we calculate argument lengths and store lengths in table ArgLens:
    xor eax,eax     ; Searching for 0, so clear AL to 0
    xor ebx,ebx     ; Stack address offset starts at 0
ScanOne:
    mov ecx,0000ffffh   ; Limit search to 65535 bytes max
    mov edi,dword [ebp+16+ebx*4] ; Put address of string to search in EDI
    mov edx,edi     ; Copy starting address into EDX                                                                                                                                                                                                                                                                                                         
    cld         ; Set search direction to up-memory
    repne scasb     ; Search for null (0 char) in string at edi
    jnz Error       ; REPNE SCASB ended without finding AL
    mov byte [edi-1],10 ; Store an EOL where the null used to be
    sub edi,edx     ; Subtract position of 0 from start address
    mov dword [ArgLens+ebx*4],edi   ; Put length of arg into table
    inc ebx         ; Add 1 to argument counter
    cmp ebx,44; See if arg counter exceeds argument count
    jb ScanOne      ; If not, loop back and do another one

; Display all arguments to stdout:
    xor esi,esi     ; Start (for table addressing reasons) at 0
Showem:
    mov ecx,[ebp+16+esi*4]  ; Pass offset of the message
    mov eax,4       ; Specify sys_write call
    mov ebx,1       ; Specify File Descriptor 1: Standard Output
    mov edx,[ArgLens+esi*4] ; Pass the length of the message
    int 80H         ; Make kernel call
    inc esi         ; Increment the argument counter
    cmp esi,44  ; See if we've displayed all the arguments
    jb Showem       ; If not, loop back and do another
    jmp Exit        ; We're done! Let's pack it in!

我将位移向上移动到 ScanOneShowem 中的第一个空指针到第一个环境变量 ([ebp+4+ebx*4] > [ebp+16+ebx*4])。当我与我拥有的环境变量数量(44)进行比较时,它会很好地打印它们而不会出现段错误,而与 45 相比只会出现段错误。

我尝试使用指针与零进行比较(搜索空指针):cmp dword [ebp+16+ebx*4],0h但这只是返回一个段错误。我确信空指针位于堆栈中最后一个环境变量之后,但它似乎不会执行任何其他操作。

我哪里出错了?

最佳答案

如果您的程序有 2、3 或 0 个参数,您的代码仍然可以工作吗?每个部分都由 NULL 指针(4 个字节的 0)分隔。您可以获取参数的计数并将其用作数组索引,并跳过参数,直到到达 NULL 字节。现在您有了环境 block :

enter image description here

extern printf, exit

section .data
fmtstr      db  "%s", 10, 0
fmtint      db  "%d", 10, 0

global main

section .text
main:
    push    ebp
    mov     ebp, esp

    mov     ebx, [ebp + 4]

.SkipArgs:  
    mov     edi, dword [ebp + 4 * ebx]
    inc     ebx
    test    edi, edi
    jnz     .SkipArgs

.ShowEnvBlock:
    mov     edi, dword [ebp + 4 * ebx]
    test    edi, edi
    jz      .NoMore

    push    edi
    push    fmtstr
    call    printf
    add     esp, 4 * 2
    inc     ebx
    jmp     .ShowEnvBlock

.NoMore:    
    push    0
    call    exit

是的,我在这里使用 printf,但您只需将其与系统调用交换即可。

关于linux - 在环境变量后查找空指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19963864/

相关文章:

linux - 在 ubuntu 中从 Chroot 内部运行服务器

linux - 如何将 acl 备份到文件然后将其应用到另一个文件夹?

c++ - 内联汇编,输出指令

x86 - 8088/8086 WAIT指令和BIU

c - InterlockedExchange() 类型函数/内部函数的 MSDN 文档不一致?

linux - 使用 GNU/Linux 系统调用 `splice` 在 Haskell 中进行零拷贝套接字到套接字数据传输

linux - xterm 不运行 shell 脚本

c++ - 是否可以修改内存中的函数?

c - 在 x86 和 x64 上的同一页面内读取缓冲区的末尾是否安全?

x86 汇编器 : floating point compare