在环境变量之后查找空指针

时间:2013-11-13 20:39:29

标签: linux assembly x86

我正在读一本书(汇编语言一步一步,使用Linux编程由Jeff Duntemann编写),我正在尝试更改显示该参数的程序,而不是显示环境变量。我试图只使用到目前为止所教的内容(没有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!

我将位移从第一个空指针移到[ebp+4+ebx*4] > [ebp+16+ebx*4]ScanOne中的第一个环境变量(Showem)。当我与环境变量的数量(44)进行比较时,它会在没有段错误的情况下将它们打印得很好,相比之下45只会给我一个段错误。

我尝试使用指针进行比较为零(搜索空指针):cmp dword [ebp+16+ebx*4],0h但只返回段错误。我确信空指针位于堆栈中的最后一个环境变量之后,但它就像它不会做任何事情一样。

我哪里错了?

2 个答案:

答案 0 :(得分:0)

想继续道歉,这总是发生在我身上(在询问stackoverflow问题后自己解决)。我想当我尝试将指针与0h进行比较时,我输错了一些东西。这就是我的所作所为:

inc ebx
cmp dword [ebp+16+ebx*4],0h
jnz ScanOne

inc esi
cmp dword [ebp+16+esi*4],0h
jnz Showem

这很有用。

答案 1 :(得分:0)

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

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,但您只需将其与系统调用交换。