NASM - The Netwide Assembler

NASM Forum => Using NASM => Topic started by: aloha_arts on March 31, 2010, 08:41:13 PM

Title: Why simple cpuid code gives runtime error?
Post by: aloha_arts on March 31, 2010, 08:41:13 PM
Why does the following code give a runtime error?
It prints: "Vendor id: GenuineIntel" and then crashes.

compiled with: nams -fwin32 ...

Code: [Select]
    global  _main
    extern  _printf

    section .text
_main:
    push    ebx
    push    ebp


    xor     eax, eax
    cpuid

    mov     [vendor], ebx
    mov     [vendor + 4], edx
    mov     [vendor + 8], ecx

    push    vendor
    push    format
    call    _printf
    sub     esp, 4

    pop     ebp
    pop     ebx

    ret

    section .data
format      db      'Vendor id: %s', 10, 0
vendor      times   12  db  0
Title: Re: Why simple cpuid code gives runtime error?
Post by: Keith Kanios on March 31, 2010, 09:04:13 PM
At a glance, you are making 8 bytes worth the stack pushes before calling printf, and then "adding" 4 more bytes to the stack after. Remember, the stack grows downwards, not upwards.

In short, esp is 12 bytes off of where it should be.
Title: Re: Why simple cpuid code gives runtime error?
Post by: Frank Kotler on March 31, 2010, 09:13:45 PM
I would also add a byte to "vendor" and zero-terminate it...

Best,
Frank

Title: Re: Why simple cpuid code gives runtime error?
Post by: Keith Kanios on March 31, 2010, 11:01:52 PM
I would also add a byte to "vendor" and zero-terminate it...

Most definitely. Good catch.
Title: Re: Why simple cpuid code gives runtime error?
Post by: Frank Kotler on April 01, 2010, 01:35:23 AM
Just for fun, here's a more verbose subfunction(?) of cpuid.

Code: [Select]
; nasm -f elf cpuname.asm
; ld -o cpuname cpuname.o

global _start

section .bss
    namestring resb 48

section .text
_start:

    mov eax, 80000000h
    cpuid
    cmp eax, 80000004h ; supported?
    jb exit
   
    mov edi, namestring

    mov eax, 80000002h
    cpuid
    call savestring

    mov eax, 80000003h
    cpuid
    call savestring

    mov eax, 80000004h
    cpuid
    call savestring

    mov ecx, namestring ; buffer
    mov edx, 48 ; length
    mov ebx, 1 ; stdout
    mov eax, 4 ; sys_write
    int 80h

exit:
    mov eax, 1
    int 80h
;-----------------------

savestring:
    stosd
    mov eax, ebx
    stosd
    mov eax, ecx
    stosd
    mov eax, edx
    stosd
    ret

The astute observer will note that I didn't leave a space for a zero terminator either. Well, I didn't need one, I know the length. I should have added another byte and stuffed a linefeed in there, though! Oh, well. :)

The conversion to Windows/_printf should be easy - don't forget to preserve the necessary registers if you're going to exit with "ret"! (sys_exit doesn't care).

Best,
Frank

Title: Re: Why simple cpuid code gives runtime error?
Post by: aloha_arts on April 01, 2010, 01:56:30 PM
Thank you. You where rigth about the esp line.
:)

Do you know where I can read through some NASM tutorials for windows programming and interrups?