Вот этот код:
.intel_syntax noprefix

.section .rwplt, "axw"

.global stub0, stub1, stub2, stub3, stub4, stub5
stub0:
    call fix_stub          # 5 bytes
stub1:
    call fix_stub          # 5 bytes
stub2:
    call fix_stub          # 5 bytes
stub3:
    call fix_stub          # 5 bytes
stub4:
    call fix_stub          # 5 bytes
stub5:
    call fix_stub          # 5 bytes

.section .text
.global fix_stub
.type fix_stub, @function

fix_stub:
    # Сохранение регистров
    push    rbp
    mov     rbp, rsp
    sub     rsp, 16          # Выделение места на стеке

    # Шаг 1: Извлечение адреса возврата из стека
    mov     rax, [rsp + 8]   # [rbp+16] если использовать rbp
    sub     rax, 5            # rax теперь указывает на stubN

    # Шаг 2: Вычисление N = (stubN - rwplt_start) / 5
    lea     rbx, [rip + rwplt_start]  # Загружаем адрес rwplt_start
    sub     rax, rbx          # rax = stubN - rwplt_start
    mov     ecx, 5            # Делитель
    xor     rdx, rdx          # Очищаем RDX для деления
    div     ecx                # rax = N, rdx = 0

    # Шаг 3: Вызов resolve(N)
    mov     edi, eax          # Перемещаем N в EDI (первый аргумент)
    call    resolve            # Вызов resolve(N), результат в RAX

    # Шаг 4: Вычисление rel32 = funcN - (stubN + 5)
    mov     rbx, rax          # rbx = funcN
    mov     rcx, [rsp + 8]    # rcx = stubN + 5
    sub     rbx, rcx          # rbx = funcN - (stubN + 5)
    mov     esi, ebx          # Перемещаем младшие 32 бита в esi (rel32)

    # Шаг 5: Перезапись stubN с помощью 'jmp rel32' (E9 <rel32>)
    mov     byte ptr [rax], 0xE9      # Opcode для JMP rel32
    mov     dword ptr [rax + 1], esi  # Записываем rel32

    # Шаг 6: Переход к funcN
    mov     rax, rbx          # Перемещаем адрес funcN в RAX
    jmp     rax               # Переход к funcN

    # Эпилог
    leave
    ret

.section .text
rwplt_start:
    .quad   stub0
    .quad   stub1
    .quad   stub2
    .quad   stub3
    .quad   stub4
    .quad   stub5

Должен решать задачу:
В тестирующей программе имеется 6 подпрограмм func0, func1, ..., func5, адреса которых в памяти неизвестны, и подпрограмма void* resolve(int N), которая возвращает адрес подпрограммы funcN. К сожалению, resolve работает довольно медленно, и нам хотелось бы избежать лишних вызовов resolve.

Определите в сдаваемом файле секцию .rwplt, доступную для записи и исполнения кода, следующим образом:

.section .rwplt, "axw"
Определите в секции .rwplt 6 меток stub0, stub1, ..., stub5 таким образом, чтобы:

при первом вызове call stubN сначала вызывалась функция resolve(N), а затем происходил переход в функцию funcN;
при последующих вызовах call stubN сразу происходил переход в функцию funcN.
Указание: напишите в секции .text вспомогательную подпрограмму fix_stub, которая вызывает resolve и записывает после метки stubN новый машинный код.

Секция .rwplt должна иметь размер не более 48 байт. Секции .data (и других writeable секций) в сдаваемом файле быть не должно.

Гарантируется, что общий размер всех секций программы не превышает 2 ГБ.

Игнорируйте следующее предупреждение компоновщика:

/usr/bin/ld: warning: program has a LOAD segment with RWX permissions
Бонус: попробуйте обойтись 35 байтами в секции .rwplt.

Тестировать решение можно с помощью нижеследующего main.c, однако обратите внимание, что в тестирующей системе функции func[0-5] другие — например, у них могут быть разные наборы и типы параметров.

#include <stdio.h>

static int func0(int a, int b) {
    return a + b;
}
static int func1(int a, int b) {
    return a - b;
}
static int func2(int a, int b) {
    return a * b;
}
static int func3(int a, int b) {
    return a / b;
}
static int func4(int a, int b) {
    return a % b;
}
static int func5(int a, int b) {
    return a & b;
}
int stub0(int a, int b);
int stub1(int a, int b);
int stub2(int a, int b);
int stub3(int a, int b);
int stub4(int a, int b);
int stub5(int a, int b);

typedef int (*func_t)(int, int);
func_t funcs[] = {func0, func1, func2, func3, func4, func5};
func_t stubs[] = {stub0, stub1, stub2, stub3, stub4, stub5};

func_t resolve(unsigned a) {
    printf("resolve %u\n", a);
    return funcs[a];
}

int main() {
    int fn, a, b;
    while (scanf("%d %d %d", &fn, &a, &b) == 3) {
        int result = stubs[fn](a, b);
        printf("%d\n", result);
    }
    return 0;
}
      
но выдает ошибку:

/usr/bin/ld: /tmp/ccdtTo1Z.o: warning: relocation against `stub5' in read-only section `.text'