我正在读一本书(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!
我将位移向上移动到 ScanOne
和 Showem
中的第一个空指针到第一个环境变量 ([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 :
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/