Статически загруженный C в сборку aarch64 для учебных целей

Я хочу изучить ассемблер и решил, что компиляция кода C в ассемблер будет хорошим началом. То есть: cc main.c -S который компилируется

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
}

к

    .section    __TEXT,__text,regular,pure_instructions
    .build_version macos, 14, 0 sdk_version 14, 5
    .globl  _main                           ; -- Begin function main
    .p2align    2
_main:                                  ; @main
    .cfi_startproc
; %bb.0:
    stp x29, x30, [sp, #-16]!           ; 16-byte Folded Spill
    .cfi_def_cfa_offset 16
    mov x29, sp
    .cfi_def_cfa w29, 16
    .cfi_offset w30, -8
    .cfi_offset w29, -16
    adrp    x0, l_.str@PAGE
    add x0, x0, l_.str@PAGEOFF
    bl  _printf
    mov w0, #0
    ldp x29, x30, [sp], #16             ; 16-byte Folded Reload
    ret
    .cfi_endproc
                                        ; -- End function
    .section    __TEXT,__cstring,cstring_literals
l_.str:                                 ; @.str
    .asciz  "Hello, World!\n"

.subsections_via_symbols

... Как видите, я использую aarch64. Но проблема не в этом:

as main.s все еще нет проблем. Но когда я это делаю ld a.out:

Undefined symbols for architecture arm64:
  "_printf", referenced from:
      _main in a.out
ld: symbol(s) not found for architecture arm64

Я уже нашел решение этой проблемы в каком-то малоизвестном, почти совершенно несвязанном сообщении в блоге, поэтому:
ld a.out -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/ -lSystem

и теперь это работает.

$ ./a.out
Hello, World!

Итак, вот вопрос: откуда мне знать, как определяется _printf? То есть я уже знаю, как поставить syscall и написать stdout, но для чего-то более сложного это станет такой рутиной. Весь смысл в том, чтобы я выучил Ассемблер, но динамическое связывание очень затрудняет это. Если бы я мог статически связать это, это сделало бы все намного проще. Есть ли компилятор, который позволяет это? Кстати, я использую clang:

$ cc --version
Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64-apple-darwin23.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Я попробовал следующим образом:

$ cc main.c -static
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)

и

$ cc main.c -lstatic
ld: library 'static' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)

и

$ cc main.c -static -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)

и когда я это сделаю

$ cc main.c -static -S

-static просто игнорируют.

Я пробовал много чего другого; некоторые я не помню, некоторые я не могу записать. Вы уловили суть. Пожалуйста помоги.

Обратите внимание: если вы готовы использовать cc для ссылки, он должен добавить соответствующие флаги для вас, чтобы вам не пришлось беспокоиться. Тем не менее, я предполагаю, что все компоненты библиотеки C будут находиться рядом printf, поэтому то, что у вас есть, должно работать и для других функций. Для сторонних материалов, даже со статическим связыванием, вам все равно нужно будет указать библиотеку, так что это та же проблема.

Jester 27.05.2024 03:35

если вы хотите изучить ассемблер, то это не программа для сборки unsigned int fun ( unsigned int x) { return x+5; } значительно лучше. и скомпилировать с оптимизацией...

old_timer 27.05.2024 05:51

Статическая ссылка в этом не поможет. cc -S по-прежнему будет выдавать только сборку исходного кода C, который вы на самом деле компилируете, а не код библиотеки, который был давно скомпилирован поставщиком ОС; cc -S вообще не делает никаких ссылок. Если вы хотите увидеть ассемблерный код printf, вы можете дизассемблировать стандартную динамическую библиотеку C с помощью objdump --disassemble, но я могу вам сразу сказать, что дизассемблирование такой длинной и сложной функции не будет очень познавательным.

Nate Eldredge 27.05.2024 07:15

Если вы хотите узнать, как работает printf, начните с чтения исходного кода C типичной реализации, например. github.com/lattera/openbsd/blob/master/lib/libc/stdio/…. Но опять же, если вы хотите выполнить определенную задачу форматирования на ассемблере, вам, вероятно, лучше начать с нуля.

Nate Eldredge 27.05.2024 07:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете дизассемблировать статический объектный файл, выполнив следующие действия:

gcc -march=native -static main.c -o main.o 
objdump -drwC -Mintel main.o > main.s

$ gcc -march=native -static main.c -o main.o ld: библиотека не найдена для -lcrt0.o clang: ошибка: команда компоновщика завершилась неудачей с кодом выхода 1 (используйте -v, чтобы увидеть вызов)

voltaire 27.05.2024 07:09

Apple не поддерживает статически связанные двоичные файлы в Mac OS X (см. здесь). Возможно, вам придется переключиться на другую ОС, например Linux.

Lincoln06 27.05.2024 08:21

Честно говоря, мне очень хочется, но я не думаю, что Asahi Linux еще существует, а я слишком беден, чтобы позволить себе еще один компьютер...

voltaire 27.05.2024 17:56

Другие вопросы по теме