Постигнете C кастинг с помощта на x86 mov инструкции

Чета книгата "Компютърни системи: гледна точка на програмиста". Точно сега не съм много сигурен, че разбирам кога да използвам различните инструкции за mov. Ето го упражнението:

Практически проблем 3.4

Да приемем, че променливите v и p са декларирани с типове

src_t v;

dest_t *p;

където src_t и dest_t са типове данни, декларирани с typedef. Искаме да използваме подходящата инструкция за движение на данни, за да изпълним операцията

*p = (dest_t) v;

където v се съхранява в подходящо наречената част на регистър %eax (т.е. %eax, %ax или %al), докато указателят p се съхранява в регистър %edx.

За следните комбинации от src_t и dest_t напишете ред асемблерен код, който извършва подходящото прехвърляне. Спомнете си, че когато извършвате преобразуване, което включва както промяна на размера, така и промяна на „подпис“ в C, операцията трябва първо да промени подписа (раздел 2.2.6).

Проверявам решенията си спрямо тази публикация в блога и не съм съвсем сигурен, че разбирам проблем 3:

src_t       dest_t      My Solution              Blog's Solution

char        unsigned    movzbl %al, (%edx)     movsbl %al, (%edx)

Номер 3: Аз използвам movzbl, докато авторът на блога използва movsbl. Не разбирам мотивите на movzbl срещу movsbl в този случай... Ако символът е отрицателен, така или иначе ще се окажете с грешно число, може ли някой да изясни защо movsbl е правилният избор тук?


person Augusto Dias Noronha    schedule 08.04.2015    source източник
comment
Това зависи изцяло от това дали char е със знак или без знак. Това е дефинирано от изпълнението, така че и двете решения са еднакво правилни, като се има предвид съответстващото изпълнение.   -  person Jester    schedule 08.04.2015
comment
@Jester Мисля, че char е подписано в този случай, други проблеми имат unsigned char, така че мисля, че липсата му означава, че този е подписан.   -  person Augusto Dias Noronha    schedule 08.04.2015
comment
Ако char е подписано, трябва да използвате movsbl, за да го разширите. Например, ако вашата стойност на char е -1, вие искате стойността unsigned int да бъде 0xffffffff (това се изисква от стандарта C).   -  person Jester    schedule 08.04.2015
comment
Разбирам... Не ми стана съвсем ясно какви са правилата в случая. Благодаря ти за помощта   -  person Augusto Dias Noronha    schedule 08.04.2015


Отговори (1)


Спомнете си, че когато извършвате преобразуване, което включва както промяна на размера, така и промяна на „подпис“ в C, операцията трябва първо да промени подписа (раздел 2.2.6).

Освен ако не го чета погрешно, това изречение изглежда противоречи на това, което той дава като правилен отговор.

Това правило би означавало, че започвайки със знаков знак:

  • знак със знак
  • -> неподписан символ
  • -> unsigned int

Така че преобразуването на размера е от unsigned char към unsigned int, така че movz би било подходящо. Вероятно правилото е погрешно (не съвпада с това, което C всъщност определя) и movs наистина е това, което C компилаторът би използвал.

Коментарът на Jester казва, че unsigned int стойността на -1 char стойност трябва да бъде 0xffffffff, така че изглежда, че последното изречение от практическия проблем относно реда на преобразуване на знака и размера е проблемът.

person Peter Cordes    schedule 25.06.2015
comment
Грешки в книгата: Практически проблем 3.4. Последното изречение от изложението на проблема трябва да гласи „... операцията трябва първо да промени размера ....“ - person Rodrigo Camargos; 03.10.2018