我已经用 C++ 编写了一个函数,我需要用汇编代码替换它,并使用 VS2019 IDE 的汇编插入插入格式它,有人可以帮忙或告诉我在哪里可以阅读到此内容吗?该函数获取输入的姓名和年龄并将它们插入到列表中。下面是代码本身。
void insert(Node*& head, const char* name, const char* age) {
Node* newNode = new Node;
strncpy_s(newNode->name, name, 8);
newNode->name[8] = '\0'; // Обеспечиваем корректное завершение строки
strncpy_s(newNode->age, age, 2);
newNode->age[2] = '\0';
newNode->next = nullptr;
if (head == nullptr || strcmp(name, head->name) < 0) {
// Вставка в начало списка
newNode->next = head;
head = newNode;
}
else {
Node* current = head;
while (current->next != nullptr && strcmp(name, current->next->name) > 0) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
用汇编语言编写的代码
void insert(Node*& head, const char* name, const char* age) {
__asm {
// Входные параметры:
// head (esi) - указатель на указатель на голову списка
// name (edx) - указатель на строку имени
// age (ecx) - указатель на строку возраста
// Сохраняем текущие значения регистров
push ebx
push edi
push esi
push edx
push ecx
// Получаем указатель на голову списка
mov esi, [esp + 20] // head
mov edx, [esp + 24] // name
mov ecx, [esp + 28] // age
// Выделяем память для нового узла (Node)
push 8 // Размер структуры Node (9 байт для name, 3 для age, 4 для next)
call malloc // Вызов malloc
add esp, 4 // Очистка стека после вызова malloc
mov ebx, eax // Новый узел сохраняем в ebx
// Копируем имя в новый узел (newNode->name)
lea edi, [ebx] // edi указывает на новый узел
lea eax, [edi + 0] // Адрес поля name в новом узле
mov ebx, edx // ebx указывает на строку name
call strncpy_s // Копирование строки name
// Завершаем строку null-символом для name
lea eax, [edi + 8]
mov byte ptr[eax], 0
// Копируем возраст в новый узел (newNode->age)
lea eax, [edi + 8] // Адрес поля age в новом узле
mov ebx, ecx // ebx указывает на строку age
call strncpy_s // Копирование строки age
// Завершаем строку null-символом для age
lea eax, [edi + 10]
mov byte ptr[eax], 0
// Устанавливаем указатель next в nullptr
lea eax, [edi + 12] // Адрес поля next
mov dword ptr[eax], 0 // newNode->next = nullptr
// Если список пуст (head == nullptr), вставляем в начало
mov eax, [esi] // Загружаем head
cmp eax, 0 // Если head == nullptr
je InsertAtStart // Переход к вставке в начало
// Если список не пуст, ищем место для вставки
SearchLoop :
mov edx, [eax + 0] // Загружаем имя текущего узла
lea ecx, [edi + 0] // Адрес нового имени (name)
call strcmp // Сравниваем строки
jg ContinueSearch // Если current->name > newNode->name, продолжаем
// Вставляем узел после текущего
mov edx, [eax + 4] // Загружаем указатель на следующий узел
lea ecx, [edi + 12] // Адрес next нового узла
mov[ecx], edx // newNode->next = current->next
lea edx, [eax + 4] // Адрес next текущего узла
lea ecx, [edi + 12] // Адрес next нового узла
mov[edx], ecx // current->next = newNode
jmp EndInsert
ContinueSearch :
mov eax, [eax + 4] // Переходим к следующему узлу
jnz SearchLoop // Если не конец списка, продолжаем
InsertAtStart :
// Вставка в начало списка
lea eax, [edi + 12] // Адрес поля next в новом узле
mov dword ptr[eax], [esi] // newNode->next = *head
mov[esi], ebx // *head = newNode
EndInsert :
// Восстанавливаем регистры
pop ecx
pop edx
pop esi
pop edi
pop ebx
}
}