如何从全局原子 table 中获取字符串?

How can I get a string from the global atom table?

几天来,我一直在尝试为 windows OS 编写汇编程序。 我试图在全局原子 table 中存储一个字符串,然后再取回它。

问题是:当我调用函数 GlobalGetAtomNameA 时,程序崩溃,代码为 5,访问冲突! 这是我写的代码:

GLOBAL  _main   ; Entrypoint

EXTERN  printf                      ; msvcrt.dll

EXTERN  GlobalAddAtomA
EXTERN  GlobalDeleteAtom
EXTERN  GlobalFindAtomA
EXTERN  GlobalGetAtomNameA          ; kernel32.dll (and umengx86.dll?)

EXTERN  SetLastError
EXTERN  GetLastError                ; Errhandlingapi.h

EXTERN  LoadLibraryA                ; libloaderapi.h

EXTERN  ExitProcess

SEGMENT .data
LoadLib     DB "User32", 0x00

AtomString  DB "This is a string I want to store in the Global Atom Table!", 0x00
AtomFailed  DB "Oops! Something went wrong:", 0x0A, 0x00
AtomSucceed DB "Data stored successfully!", 0x00

String1     DB "Here is the string:", 0x0A, 0x00

ErrCode5    DB "Error: Access denied!", 0x00

SEGMENT .bss
AtomPTR:        resb 2          ; Atom will be 2 bytes long
AtomBuffer:     resb 100        ; Where the received message gets stored

SEGMENT .text
_main:
    PUSH LoadLib
    CALL LoadLibraryA           ; explicitly load this library into memory
    ADD esp, 4                  ; if this isn't done, GlobalAddAtomA will return NULL

    CMP eax, 0x00               ; if function returns 0, something went wrong
    JE Fail



    PUSH AtomString
    CALL GlobalAddAtomA         ; Call function
    ADD esp, 4                  ; Data stored as atom can have a maximum size of 255 bytes

    CMP ax, 0x00
    JE Fail



    MOV WORD[AtomPTR], ax           ; Copy Atom into memory (16 bits)

    PUSH AtomSucceed
    CALL printf
    ADD esp, 4



    PUSH AtomString
    CALL GlobalFindAtomA            ; Search for our string
    ADD esp, 4

    MOV bx, WORD[AtomPTR]           
    CMP ax, bx                      ; CMP these two atoms
    JNE Fail                        ; If they don't match, something went wrong



    PUSH 0x64                       ; 3rd arg: Buffer size
    PUSH AtomBuffer                 ; 2nd arg: Buffer for the retrieved value
    PUSH ax                         ; 1st arg: Atom

    CALL GlobalGetAtomNameA         ; Get String back
   ; Program crashes inside this function

    ADD esp, 10                     ; 3rd & 2nd arg: 4 bytes | ax: 2 bytes



    PUSH AtomBuffer
    CALL printf
    ADD esp, 4                      ; Print out the retrieved string



    XOR eax, eax
    PUSH eax
    CALL SetLastError               ; Set last error to 0x00
    ADD esp, 4

    MOV ax, WORD[AtomPTR]
    PUSH ax
    CALL GlobalDeleteAtom           ; Delete Atom from Table
    ADD esp, 2                      ; ax is only 2 bytes

    CALL GetLastError               ; If last error has changed from 0x00,
    CMP ax, 0x00                    ; something went wrong
    JNE Fail


ExitProc:
    XOR eax, eax
    PUSH eax
    CALL ExitProcess

; ----------------------------------------------------- ;   

Fail:
    PUSH AtomFailed
    CALL printf
    ADD esp, 4



    CALL GetLastError       ; No arguments

    CMP ax, 0x05
    JNE ExitProc            ; If not error code 5, exit

    PUSH ErrCode5           ; If error code 5, printf
    CALL printf
    ADD esp, 4



    JMP ExitProc            ; Exit

我用nasm制作.obj文件:

nasm -fwin32 Atoms.asm

我 link 使用 GoLink:

GoLink.exe /mix /console /entry _main Atoms.obj kernel32.dll user32.dll msvcrt.dll libloaderapi.h Errhandlingapi.h

当我在调试器中运行程序时,我看到程序崩溃在umengx86.dll的地址space。这是什么文件?

我尝试 link umengx86.dll 使用我的 .obj 文件,但这也没有用。

你能告诉我问题出在哪里吗?

感谢您的帮助!

PUSH ax 仅压入 16 位,但调用约定在完整的 4 字节堆栈槽中传递窄整数。

使用 movzx eax, word [...] 窄数据负载,这样您就不必在 16 位操作数大小上胡思乱想了。

然后你可以使用 push eax 在高 2 个字节中无垃圾地推送,以防你的被调用者想要 int 而不是 short。如果它只查看低 2 个字节,则上半部分的内容无关紧要,但您肯定需要 push eax.