Search code examples
cassemblyinline-assembly

Assembly code in C break instruction to get current time


I need to write inline assembly code in C in format like this:

asm(
    "mov %1, %%ax\n\t"
    "inc %%ax\n"
    "mov %%ax, %0"
    :"=r" (a)
    :"r" (a)
    );

This code in asm() need to do break and assign current time to variables declared in C outside of asm() func. I have tried to write my own code but I even struggle to do break instruction... I'm on intel and using codeblock. Any good sources of inline-assembly are welcome too. EDIT: I need something like this:

int 21h -> break
AH = 2Ah
CX -> year
DH -> month
DL -> day
AH = 2Ch
CH -> hour
CL -> min
DH -> sec
RET

Solution

  • In general, when using gcc inline asm on x86, you NEVER want to include mov instructions, or explicit registers in the asm code. Instead, you want to use the constraints to force inputs and output into specific registers. The constraints available are:

    +---+--------------------+
    | r |    Register(s)     |
    +---+--------------------+
    | a |   %eax, %ax, %al   |
    | b |   %ebx, %bx, %bl   |
    | c |   %ecx, %cx, %cl   |
    | d |   %edx, %dx, %dl   |
    | S |   %esi, %si        |
    | D |   %edi, %di        |
    +---+--------------------+
    

    This means that your increment example (putting a value into ax and incrementing) can be much more effectively written as:

    asm("inc %0" : "+a" (a))
    

    This forces the variable a into the ax register (assuming it is a 16-bit value) and increments it there.

    One tricky problem is there are no constraints for h registers (upper 8 bits of 16 bit registers). So if you want to do things with those, you need to use a 16 bit value and explicitly pack/unpack the pairs. So for your int 21h/2Ah call, you would use something like:

    uint16_t year, month_day;
    asm("int 0x21" : "=c" (year), "=d" (month_day) : "a" (0x2a00));
    uint8_t month = month_day >> 8;
    uint8_t day = month_day;