Программирование на С - PullRequest
       33

Программирование на С

0 голосов
/ 22 марта 2012

У меня все работает, спасибо всем!

У меня есть домашняя работа, чтобы написать программу сборки mulq.s, которая идет в комплекте с моей программой C bigmult.c

Программа C должнаумножить два беззнаковых шестнадцатеричных числа вместе.Я начал, но думаю, мне нужна большая помощь.Это введение в сборку, так что это не очень долго.

Вот полный вопрос:

Вы должны написать программу на языке C с именем big_mult.c, которая умножает два целых числа без знака, x и y, прочитанных из командной строки.Выходные данные представляют собой пару целых чисел без знака, представляющих наиболее значимые и наименее значимые 64 бита полного 128-разрядного произведения x * y.Входы и выходы должны быть представлены в шестнадцатеричном формате.Ваша C-программа позаботится о том, чтобы прочитать входные данные и распечатать выходные данные, но она вызовет функцию mull.s для выполнения фактического умножения.Ваша программа на C должна использовать только переменные типа int или unsigned int и не должна выполнять арифметику.Функция, определенная mull.s, должна иметь следующую декларацию в C перед процедурой main.void mull (без знака int x, без знака int y, без знака int * high, без знака int * low);Младшие 64 бита продукта должны быть назначены на низкий уровень, а старшие 64 бита продукта должны быть назначены на высокий.Не забудьте поместить соответствующий заголовочный комментарий в ваш файл сборки (обычный комментарий C / * ... * / будет работать и для сборки).Один из подходов к написанию этой ассемблерной программы - написать аналогичную программу на C, скомпилировать ее в код ассемблера с помощью опции -S и изменить полученный код ассемблера так, чтобы он делал то, что вам нужно.Ваш код окончательной сборки должен быть очень коротким и содержать только одну инструкцию умножения.

Я начал писать фиктивную программу, чтобы получить неважные части кода сверху, а затем я полностью потерянна что делать.У меня есть инструкция pushq, чтобы нажать% rbp и переместить адрес в% rsp.Что я должен делать после этого?

Любые намеки приветствуются!

Мой код на данный момент:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:
    pushq   %rbp
    movq    %rsp, %rbp

Моя программа на C:

#include <stdio.h>
void mull(unsigned int x, unsigned int y, unsigned int* high, unsigned int* low);
int main(int argc, char* argv[]) {
    unsigned long long int x, y;
    if(argc != 3)
        printf("Usage: bigmult x1 x2 <where x1 and x2 are hexadecimal integers>\n");
    else {
        sscanf(argv[1], "%x", &x);
        sscanf(argv[2], "%x", &y);
        printf("%x x %x = ", x, y);
        mull(x, y, &x, &y);
    }
    return 0;
}

1 Ответ

2 голосов
/ 22 марта 2012

Я хотел бы добавить свой собственный комментарий, но правила! # * & $% Stackoverflow запрещают мне комментировать, пока у меня не будет 28 миллионов кредитных пунктов (возможно, немного меньше).

Прежде всего, вы хотите написать свою функцию mull () на C настолько просто, насколько это возможно. Результирующий код будет проще (НАМНОГО проще), если вы будете использовать в качестве входных данных два 32-битных целых числа (вероятно, просто 'int', но зависит от вашей платформы). Если вы делаете это, судя по комментариям вашего профессора, это должно сводиться к одной инструкции умножения, которая выполняет 32-битное * 32-битное = 64-битное умножение. Если вы используете 64-битные целые числа в качестве входных данных, на вашем ЦП может не быть инструкции 64-битная * 64-битная = 128-битная, но даже если это слишком для вашего назначения. Если этого не произойдет, то компилятор выдаст последовательность инструкций для выполнения 64-битного * 64-битного = 128-битного умножения, что значительно затруднит вам понимание того, что происходит.

Когда вы получаете отдельную сборку C-файла для объектного файла и связываетесь с объектным файлом main (), вам нужно выполнить его разборку и найти инструкцию умножения. Как только вы нашли его, проследите назад, чтобы выяснить, откуда пришли его аргументы ... они могут быть в регистрах или, возможно, в ячейках памяти в стеке, в зависимости от ABI вашей системы. Затем проследуйте вперед до возврата функции, чтобы увидеть, куда идут результаты умножения, когда оно возвращается вызывающей стороне.

Возможно, вы захотите продублировать эту функциональность в вашей сборочной версии mult (), но за этим исключением: скомпилированная версия C-кода, вероятно, включает в себя хороший набор прологов и инструкций эпилога, которые просто не нужны в функции, которая так же просто, как Mult (). Но если компилятор действительно хорош в оптимизации, он не заметит этого, и скомпилированный результат будет, вероятно, в восемь раз дольше, чем это действительно необходимо. Судя по комментариям вашего профессора, вся ваша функция Mult () может быть всего от 2 до 6 инструкций ... и, в зависимости от вашего ABI, вам может понадобиться, а может и не понадобиться стек. (Для x86 вы это сделаете, но для PowerPC или других машин RISC вам не понадобится такая простая функция, поскольку для многих машин RISC функции с несколькими аргументами передают все свои аргументы в регистры, поэтому им не нужно стек вообще.)

Итак, если вам НЕОБХОДИМО использовать стек, ваша функция может выглядеть примерно так:

_mult:
   ...instructions to move parameters from stack locations into registers...
   ...multiply instruction using those registers...
   ...instructions to move the results into the appropriate stack locations
      for return values (or return value registers, depending on your ABI)...
   ...and finally, your processor's "return" instruction

... всего, возможно, максимум 6 инструкций.

...