Перевести VS встроенный ассемблер в GCC встроенный ассемблер - PullRequest
0 голосов
/ 10 декабря 2018

Я нахожу этот код C со встроенным кодом ассемблера:

ReadFromCMOS (unsigned char array [])
{
   unsigned char tvalue, index;

   for(index = 0; index < 128; index++)
   {
      _asm
      {
         cli             /* Disable interrupts*/
         mov al, index   /* Move index address*/
         /* since the 0x80 bit of al is not set, NMI is active */
         out 0x70,al     /* Copy address to CMOS register*/
         /* some kind of real delay here is probably best */
         in al,0x71      /* Fetch 1 byte to al*/
         sti             /* Enable interrupts*/
         mov tvalue,al
       }

       array[index] = tvalue;
   }
}

WriteTOCMOS(unsigned char array[])
{
   unsigned char index;

   for(index = 0; index < 128; index++)
   {
      unsigned char tvalue = array[index];
      _asm
      {
         cli             /* Clear interrupts*/
         mov al,index    /* move index address*/
         out 0x70,al     /* copy address to CMOS register*/
         /* some kind of real delay here is probably best */
         mov al,tvalue   /* move value to al*/
         out 0x71,al     /* write 1 byte to CMOS*/
         sti             /* Enable interrupts*/
      }
   }
}

Я пытался перевести на встроенный ассемблер GNU, но мне не удалось, в основном потому, что встроенный ассемблер GNU грязный, использует архаичный синтаксис AT & T итрудно использовать.

Код, который дает мне ошибку:

void read_cmos(unsigned char array[])
{
    unsigned char tvalue, index;
    for (index = 0; index < 128; ++index)
    {
        /* read from CMOS */
        asm ("cli; outb %1, $0x70; inb $0x71, %0; sti" : "=a"(tvalue) : "a"(index));
    }
    array[index] = tvalue;
}

1 Ответ

0 голосов
/ 10 декабря 2018

Попробуйте что-то вроде этого:

/* read from CMOS */
asm ("cli; outb %1, $0x70; inb $0x71, %0; sti" : "=a"(tvalue) : "a"(index));

/* write to CMOS */
unsigned char i = index;
asm volatile ("cli; outb %0, $0x70; movb %1, %%al; outb %%al, $0x71; sti" : "+a"(i) : "rm"(tvalue));

Обратите внимание, что использование дополнительной переменной для tvalue необязательно.Вы также можете указать

"+a"(array[index])

или

"a"(array[index])

напрямую.Важно то, что переданное вами выражение имеет тип байтового размера, поэтому gcc выбирает al вместо eax.

Назначение index для i необходимо для того, чтобы al был перекрытбез изменения значения index.Этот код должен просто работать.В качестве альтернативы второй набор инструкций также можно разделить на две:

asm volatile ("cli; outb %0, $0x70" :: "a"(index));
asm volatile ("outb %0, %0x71" :: "a"(tvalue));

Это позволяет избежать необходимости в дополнительной переменной и дает большую гибкость компилятору при выборе регистров.

...