2016-07-18 7 views
0

В настоящее время я изучаю код запуска Linux, но небольшая проблема беспокоит меня.Почему язык сборки GAS может вызвать глобальную переменную языка C непосредственно без объявления?

setup.c:

unsigned int __atags_pointer __initdata; 

голова common.S

.align 2 
    .type __mmap_switched_data, %object 
__mmap_switched_data: 
    .long __data_loc      @ r4 
    .long _sdata       @ r5 
    .long __bss_start      @ r6 
    .long _end       @ r7 
    .long processor_id     @ r4 
    .long __machine_arch_type    @ r5 
    .long __atags_pointer     @ r6 
    .long cr_alignment     @ r7 
    .long init_thread_union + THREAD_START_SP @ sp 
    .size __mmap_switched_data, . - __mmap_switched_data 

линия .long __atags_pointer @ r6 в головными common.S называет глобальную переменную в setup.c без каких-либо заявлений, , таких как .global __atags_pointer. Почему это работает?

+2

Поскольку сборник GNU не является C или любым другим диалектом сборки? Я не уверен, что есть большая часть ответа за пределами «потому что [это как раз так.] (Https://www.sourceware.org/binutils/docs/as/Extern.html#Extern)» – Notlikethat

+0

Насколько я знаете, в общем, язык ассемблера GNU будет делать объявление, когда он вызывает глобальную переменную C-файла. –

+1

А? Как говорят документы, нет даже такой вещи, как декларация. Любой ссылочный символ, который не имеет локального определения, просто _assumed_ является внешним; вот и все. – Notlikethat

ответ

0

Я не думаю, что:

.long __atags_pointer 

это вызов. Это псевдо-выражение. В этом случае я думаю, что он создает пространство в 4 байта и оставляет маркер для компоновщика, чтобы заполнить пробел значением во время ссылки. Из руководства по газу:

«.long» - это то же самое, что и «.int». * Примечание '.int': Int.

7,44 «» .int САМОВЫРАЖЕНИЯ

Ожидать ноль или более выражений, любой секции, разделенных запятыми. Для каждого выражения испускайте число, которое во время выполнения является значением этого выражения. Порядок байтов и размер бита числа зависят от , для какой цели предназначена сборка.

Если вы скомпилируете файл в отдельности, чтобы получить .o, тогда запустите objdump -D на нем, я полагаю, вы увидите, что в пространстве есть все 0. Однако после того, как вы свяжетесь, в этом же пространстве будет фактическое число.

+0

Большое спасибо, я думаю, что нашел причину, как я ответил выше. –

0

.globl - это то, как вы объявляете что-то глобальное, чтобы кто-то ELSE мог его найти. В C отсутствие статичности означает, что метка глобальна, чтобы другие могли ее найти. Когда вы используете метку, ассемблер и/или компоновщик просто кладут его в таблицу вещей, которую нужно найти. Как и в C, вы идеально объявляете что-то как extern, но вам не нужно объявлять две глобальные вещи с тем же именем, и инструменты должны сортировать их, чтобы разделить этот ресурс.

То, о чем вы говорите, было объявлено глобальным кодом C, а сборка просто пытается использовать эту метку по имени.

+0

Большое спасибо, я думаю, что нашел причину, как я ответил выше. –

0

Спасибо всем! Я нашел это, как объявить! Линия .type __mmap_switched_data, %object в голова-common.S сделала заявление. Из инструкции газа:

5.5.2 Типа

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

7.94.тип

Эта директива используется для установки типа символа.

+0

А? Почему локальный символ '__mmap_switched_data', экспортируемый в компоновщик в качестве символа данных (т. Е. Более конкретный эквивалент' .global'), имеет _anything_ с использованием внешнего символа '__atags_pointer' ?? – Notlikethat