Почему операция nop вызывает sigint?

Имея это от компилятора:

.file   "b.c"
    .text
    .globl  _start
    .type   _start, @function
_start:
    pushq   %rbp
    movq    %rsp, %rbp
    nop
    popq    %rbp
    ret
    .size   _start, .-_start
    .ident  "GCC: (Debian 8.3.0-6) 8.3.0"
    .section    .note.GNU-stack,"",@progbits

должно быть просто, но почему это sigint? (Command terminated), когда ничего не делает программа?

Строить с

$cc -S -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm b.c

person Herdsman    schedule 02.06.2020    source источник
comment
nop не вызывает сигнатуры. Если это в Linux, то ret, вероятно, вызывает исключение, поскольку нет места для ret, если вы сделали точку входа своей программы в _start   -  person Michael Petch    schedule 02.06.2020
comment
почему это значение по умолчанию от компилятора gcc? (составлено void _start() { return; };). Почему компилятор использует ret, а не что-то вроде прерывания? (чтобы избежать подписи).   -  person Herdsman    schedule 02.06.2020
comment
GCC не знает, что _start особенный. Этот код C определяет _start как обычную функцию, но затем вы связываете ее (предположительно с gcc -nostdlib foo.c) как точку входа ELF. Не делай этого. _start должен быть noreturn функцией, а также вводиться с выравниванием RSP по 16 байт, а не с выравниванием по RSP + 8 по 16 байт.   -  person Peter Cordes    schedule 02.06.2020
comment
Можете ли вы показать команду, которую вы используете для создания исполняемого файла. Я предполагаю, что вы переопределяете точку входа, чтобы она указывала на _start, а не на main. Если это то, что вы делаете ... компилятор GCC не знает, кто (и если что) вызвал _start. возврат из main работает, когда используется библиотека C, потому что есть код запуска C, который инициализирует вещи, а затем вызывает main, и есть место, куда можно вернуться (код запуска C), который выполнит ожидаемое завершение. Если вы хотите, чтобы этот код завершился, вам нужно будет вызвать системный вызов выхода в конце _start.   -  person Michael Petch    schedule 02.06.2020
comment
Кроме того, вы уверены, что получили SIGINT? Я ожидал SIGSEGV.   -  person Peter Cordes    schedule 02.06.2020
comment
Все идентификаторы, начинающиеся с подчеркивания, всегда зарезервированы для использования в качестве идентификаторов с областью видимости файла как в обычном пространстве имен, так и в пространстве имен тегов. - если вы хотите играть без сети, возясь с _name идентификаторами, вы надо соблюдать правила. GCC не собирается держать вас за руку. используйте _ и __ в программах на языке C   -  person Peter Cordes    schedule 02.06.2020
comment
@PeterCordes Я не строю его с -nostdlib, я построил его, как показано по умолчанию (то есть - с операцией ret). Я не знаю, как заставить gcc строить noreturn, как вы предлагаете, но в моем случае gcc не делал этого по умолчанию   -  person Herdsman    schedule 02.06.2020
comment
Вы не можете напрямую выполнить .s файл. Если вы запускали этот код, очевидно, вам нужно было встроить его в исполняемый файл. Если вы сделали это с as + ld вручную, это эквивалентно gcc -nostdlib -static, а не построению стандартного способа для этой реализации C (где файлы реализации crt .o предоставляют _start, который был написан вручную в asm). Чтобы функция не возвращалась, вы должны вызвать такую ​​функцию, как exit или abort, которая не возвращается.   -  person Peter Cordes    schedule 02.06.2020
comment
@PeterCordes, так как я могу добавить stdlib в компиляцию as? (не gcc). Я сделал это вручную, но компилятор as должен иметь возможность связываться с другими библиотеками (такими как stdlib), тогда как я могу это сделать?   -  person Herdsman    schedule 02.06.2020
comment
as - это просто ассемблер, а не компилятор и не компоновщик. Вы можете выполнить системный вызов выхода из встроенного asm, как показано в Компиляции без libc. Но относительно: связывание по-другому: см. Также Вызов функций C из 64-битной сборки и Связывание программы с использованием printf с ld? / Как я могу динамически связать glibc в Ubuntu   -  person Peter Cordes    schedule 02.06.2020
comment
@PeterCordes для вашего первого примера (компиляция без libc), мне нужно использовать -nostartfiles, а не -nostdlib, иначе undefined reference to puts' в printf заявлении. Но тогда не понимаю разницы между этими двумя флагами, зачем использовать один вместо другого?   -  person Herdsman    schedule 02.06.2020
comment
Это правильно. В первой строке ответа говорится: Если вы скомпилируете свой код с -nostdlib, вы не сможете вызывать какие-либо функции библиотеки C (конечно). Я не знаю, что вы пытаетесь скомпилировать; все, что вы показали, это _start, который пытался ret вместо syscall. Если вы хотите использовать функции stdio (как правило, плохая идея от _start), то да, вам нужна libc, но -nostartfiles все еще может опустить код запуска CRT, который вызывает функции libc init. В GNU / Linux он может инициализироваться, если динамически скомпонован, иначе функции libc выйдут из строя.   -  person Peter Cordes    schedule 02.06.2020
comment
Может ссылку на CRT startup? Я не знаю, что это такое, кому звонит, когда звонит и зачем. Некоторые предопределенные вызовы функций мне ни о чем не говорят. Я бы хотел узнать об этом больше   -  person Herdsman    schedule 02.06.2020
comment
@PeterCordes здесь - ›в этой ссылке вы указали https://stackoverflow.com/questions/55314762/linking-a-program-using-printf-with-ld, вы используете синтаксис nasm, который имеет extern printf, но я не знаю, как сделать extern printf в газе. Кроме того, я не вижу связи с libc / glibc. В коде я вижу только ссылку на printf через extern, но при компиляции вы используете только -no-pie и -nostartfile, но не ld file.o libc.so, так откуда gcc знает об этом? Я бы хотел, чтобы это было написано на газу, чтобы увидеть это, вы можете это сделать?   -  person autistic456    schedule 04.06.2020
comment
Вам не нужен extern в GAS, любой неопределенный символ считается extern. Если у вас есть другой вопрос, например, как связать программу, использующую printf, задайте его. (Хотя это, вероятно, дубликат одного из них: ключевым моментом является gcc -no-pie -nostartfiles, а не -nostdlib, если вы хотите, чтобы GCC по-прежнему связывался с libc. GCC связывает libc по умолчанию, если вы не укажете ему не использовать -nostdlib, помните, что это интерфейс для компилятор C, а также ассемблер. Используйте gcc -v ... other options ..., чтобы узнать, какие именно команды as и ld он выполняет.)   -  person Peter Cordes    schedule 04.06.2020
comment
@PeterCordes, но я хочу СВЯЗАТЬ только с libc. То есть связал свою динамическую библиотеку с ld, что-то вроде ld file.o libc.so. Я не хочу проходить gcc, но делаю это вручную. (as- ›ld). Итак, как ДЕЙСТВИТЕЛЬНО связать libc с газом?   -  person autistic456    schedule 04.06.2020
comment
as - ассемблер, а не компоновщик. С ld, да, просто передайте свои file.o и -lc и другие необходимые параметры, например -dynamic-linker /lib64/ld-linux-x86-64.so.2. Если вы хотите узнать, как GCC вызывает ld, запустите gcc -v foo.s, а затем начните пропускать ld параметры, пока он не сломается. Тогда вы поймете, что это не было обязательным.   -  person Peter Cordes    schedule 04.06.2020