2013-07-27 4 views
19

Это мой сборочный уровень кода ...Что такое глобальный _start в языке ассемблера?

section .text 
global _start 
_start: mov eax, 4 
     mov ebx, 1 
     mov ecx, mesg 
     mov edx, size 
     int 0x80 
exit: mov eax, 1 
     int 0x80 
section .data 
mesg db  'KingKong',0xa 
size equ  $-mesg 

Выход:

[email protected]:~/Arena# nasm -f elf a.asm -o a.o 
[email protected]:~/Arena# ld -o out a.o 
[email protected]:~/Arena# ./out 
KingKong 

Мой вопрос Что такое глобальное _start используется для? Я попробовал удачу с Mr.Google, и я обнаружил, что он используется, чтобы сообщить начальную точку моей программы. Почему косяк мы просто имеем _start сказать, где программа запускается как один, приведенные ниже, который производит любопытное предупреждения на экране

section .text 
_start: mov eax, 4 
     mov ebx, 1 
     mov ecx, mesg 
     mov edx, size 
     int 0x80 
exit: mov eax, 1 
     int 0x80 
section .data 
mesg db  'KingKong',0xa 
size equ  $-mesg 

[email protected]:~/Arena# nasm -f elf a.asm 
[email protected]:~/Arena# ld -e _start -o out a.o 
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080 
[email protected]:~/Arena# ld -o out a.o 
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080 
+1

Возможный дубликат ["global main" в Assembly] (http://stackoverflow.com/questions/17882936/global-main-in-assembly) –

ответ

25

global директива является NASM специфично. Он предназначен для экспорта символов в вашем коде, где он указывает на генерируемый объектный код. Здесь вы помечаете символ _start глобально, поэтому его имя добавляется в код объекта (a.o). Линкер (ld) может читать этот символ в объектном коде и его значение, чтобы он знал, где отмечать как точку входа в выходном исполняемом файле. Когда вы запускаете исполняемый файл, он начинается с отметки _start в коде.

Если директива global отсутствует для символа, этот символ не будет помещен в таблицу экспорта объектного кода, чтобы линкер не знал о символе.

Если вы хотите использовать другое имя точки входа, чем _start (который по умолчанию), вы можете указать -e параметр Л.Д., как:

ld -e my_entry_point -o out a.o 
+1

'_start' - это только один ld« знает »по умолчанию. 'ld -o out a.o -e _main' будет работать. –

+0

Я немного поменю свой вопрос, а затем мой вопрос будет звучать немного более ясно ... – vikkyhacks

+0

@vikkyhacks, что непонятно в моем ответе? ваш вопрос, похоже, не изменился. –

2

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

Глобальный ярлык «_start» необходим компоновщику, если отсутствует глобальный адрес _start, тогда компоновщик будет жаловаться, потому что он не может найти его. Вы не объявляли _start как глобальный, поэтому он не виден вне этого модуля/объекта кода, поэтому он не отображается в компоновщике.

Это противоположность C, где вещи подразумевается, чтобы быть глобальным, если вы не объявлять их локальными

unsigned int hello; 
int fun (int a) 
{ 
    return(a+1); 
} 

привет и весело являются глобальными, видны за пределами объекта, но это

static unsigned int hello; 
static int fun (int a) 
{ 
    return(a+1); 
} 

делает их локальными не видимыми.

все местные:

_start: 
hello: 
fun: 
more_fun: 

это теперь глобальный доступны для компоновщика и других объектов

global _start 
_start: 
global hello 
hello: 
... 
+0

понимают, что эти директивы специфичны для ассемблера, программы, которая собирает язык ассемблера в машинный код. Языки ассемблера, как правило, не имеют стандартов, поэтому каждый ассемблер может сделать свое дело, обратите внимание на «формат intel» и «at & t format», который является экстремальным для одного и того же набора команд. Аналогично, некоторые могут хотеть «глобальные», а другие могут потребовать, например, «.global». Таким образом, вы изучаете нюансы инструментальной цепочки, а не обязательно набор инструкций. –

+0

хорошо, что действительно очень сложно переварить. У нас есть концепция локальных и глобальных переменных в C из-за используемых функций, есть ли области на ассемблере (ну, исправьте меня, если я ошибаюсь, я только что начал сборка) Почему не удается компоновщику просто выполнить поиск в _start в моей программе и установить начальную точку для выполнения? Какая информация ему не нужна? – vikkyhacks

+1

@vikkyhacks, я думаю, вы можете думать о методах сборки как о «статических» символах в контексте C, по крайней мере, по умолчанию. То есть, они могут использоваться только в области единиц документа/трансляции. Определение метки с помощью .global делает сборщик ассемблером (добавляет его в таблицу символов объекта), чтобы компоновщик мог найти его позже для использования в других единицах перевода (или для запуска программы в вашем случае). –

1

_start устанавливается по умолчанию скрипт на ld линкера:

ld -verbose a.o | grep ENTRY 

выходы :

ENTRY(_start) 

ELF file format (и, как мне кажется, другой формат объекта), явным образом скажу, с какого адреса программа начнет работать через поле заголовка e_entry.

ENTRY(_start) сообщает компоновщику, чтобы установить эту запись как адрес символа _start при создании файла ELF из объектных файлов.

Затем, когда ОС запускает программу (exec system call в Linux), она анализирует файл ELF, загружает исполняемый код в память и устанавливает указатель инструкции на указанный адрес.

Указанный флаг -eby Sedat переопределяет значение по умолчанию _start.

Вы можете заменить сценарий компоновщика по умолчанию опцией -T <script>.

+0

'ld -o a.o' просто говорит« нет входных файлов ». Какой вариант командной строки вы имели в виду? –

+0

@PeterCordes спасибо! Думаю, я имел в виду «-вербоз». –

0

global _start - это всего лишь метка, указывающая на адрес памяти. В случае _start, когда дело доходит до двоичных файлов ELF, это стандартная метка, которая действует как адрес, где запускается программа.

Существует также main или _main или main_ известен на языке C, и вызывается «стартовый код», который «обычно» связан - если вы используете C.

Надеются, что это помогает.

Смежные вопросы