Author Topic: calling asm from C  (Read 5072 times)

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2379
  • Country: us
calling asm from C
« on: June 30, 2011, 04:41:47 PM »
Calling C functions from asm is fun, but not that useful - could have done it all in C! Calling some asm function - something C won't do easily - from a "C main" might be more useful. I don't think C has easy access to the "cpuid" instruction (does it, C guys?), so that might make an example...

The C code:
Code: [Select]
#include <stdio.h>
int cpu_vendor(char *dest);

int main(){
    char buf[13];
    int cpuid_max_level;
   
    cpuid_max_level = cpu_vendor(buf);
    printf("vendor = %s\nmaxlevel = %d\n", buf, cpuid_max_level);
    return (0);
    };

And the asm code:
Code: [Select]
; nasm -f elf cpuvendor.asm
; nasm -f win32 --prefix _ cpuvendor.asm ???

; tell ld about us (via the .o file)
global cpu_vendor

cpu_vendor:
; C expects to have these regs preserved
    push edi
    push ebx

; our parameter, the buffer, is "up the stack",
; 4 for ebx, 4 for edi, 4 for return address = 12
    mov edi, [esp + 12]
    xor eax, eax
    cpuid

; with eax = 0, cpuid returns the vendor string
; in ebx, edx, ecx (why???), and the maximum level
; in eax (our return value). With eax greater than
; this maximum level (for this implementation of cpuid)
; cpuid returns unexpected results - 16 cores in this
; clunker? I don't think so!

; stuff the vendor string into our destination buffer
    mov [edi], ebx
    mov [edi + 4], edx
    mov [edi + 8], ecx

; don't forget to zero-terminate it!
    mov byte [edi + 12], 0

; restore caller's regs
    pop ebx
    pop edi

; we're done!
    ret
   
As usual, I haven't tested this in Windows. "Should" work - if it doesn't, holler and we'll see if we can figure out why not.

Best,
Frank


Offline MJaoune

  • Jr. Member
  • *
  • Posts: 94
Re: calling asm from C
« Reply #1 on: June 30, 2011, 04:46:43 PM »
I don't think C has easy access to the "cpuid" instruction (does it, C guys?)
No it doesn't access easily, but calling C from ASM is very useful, if you want to print something on screen you can just call the printf, without printing it from ASM which takes more time.

Best,
Mahmoud