Вывод блока GCC пустой программы на x86, win32

Является ли null экземпляром чего-либо?

blockquote>

Нет. Вот почему null instanceof X вернет false для всех классов X. (Не обманывайтесь тем фактом, что вы можете назначить null переменной, тип которой является типом объекта. Строго говоря, назначение подразумевает неявное преобразование типа, см. Ниже.)

Что устанавливает 'null' к?

blockquote>

Это единственный и единственный член нулевого типа, где нулевой тип определяется следующим образом:

«Существует также специальный тип null, тип выражения null, который не имеет имени. Поскольку тип null не имеет имени, невозможно объявить переменную нулевого типа или применить к нулевому типу. Нулевая ссылка - это единственное возможное значение выражения типа null. Нулевая ссылка всегда может быть передана любому ссылочному типу. На практике программист может игнорировать нулевой тип и просто притворяться, что null - это просто специальный литерал, который может быть любого ссылочного типа. " JLS 4.1

Что такое null?

blockquote>

См. выше. В некоторых контекстах null используется для обозначения «no object» или «unknown» или «unavailable», но эти значения являются специфичными для приложения.

Как это отображается в памяти?

blockquote>

Это специфично для реализации, и вы не сможете увидеть представление null в чистой программе Java. (Но null представляется как нулевой машинный адрес / указатель в большинстве, если не во всех реализациях Java.)

55
задан Phonon 22 June 2011 в 19:58
поделиться

5 ответов

.file "test .c "

Команды, начинающиеся с. директивы ассемблеру. Здесь просто говорится, что это "file.c", эта информация может быть экспортирована в отладочную информацию exe.

.def ___main; .scl 2; .type 32; .endef

Директивы .def определяют символ отладки. scl 2 означает класс хранилища 2 (класс внешнего хранилища). Тип 32 означает, что этот sumbol является функцией. Эти числа будут определены в формате pe-coff exe-format

___ main - это функция, вызываемая, которая заботится о начальной загрузке, необходимой gcc (она будет делать такие вещи, как запуск статических инициализаторов c ++ и другие необходимые вспомогательные операции).

. текст

Начинает текстовый раздел - здесь находится код.

.globl _main

определяет символ _main как глобальный, что делает его видимым для компоновщика и других модулей, связанных с.

 .def _main ; .scl 2; .type 32; .endef

То же, что и _main, создает символы отладки, указывающие, что _main - это функция. Это может использоваться отладчиками.

_main:

Запускает новую метку (в конце концов, это адрес). указанная выше директива .globl делает этот адрес видимым для других объектов.

 pushl% ebp

Сохраняет старый указатель кадра (регистр ebp) в стеке (чтобы его можно было вернуть на место после завершения этой функции)

 movl% esp,% ebp

Перемещает указатель стека в регистр EBP. ebp часто называют указателем кадра, он указывает на верхнюю часть значений стека в текущем «кадре» (обычно функция) (обращение к переменным в стеке через ebp может помочь отладчикам)

и l $ -16,% esp

И добавляет в стек значение fffffff0, которое эффективно выравнивает его по границе 16 байт. Доступ к выровненным значениям в стеке намного быстрее, чем если бы они не были выровнены. Все эти предыдущие инструкции в значительной степени являются прологом стандартной функции.

call        ___main

Вызывает функцию ___main, которая будет выполнять инициализацию того, что нужно gcc. Вызов поместит указатель текущей инструкции в стек и перейдет к адресу ___ main

 movl $ 0,% eax

переместите 0 в регистр eax (0 в return 0;) регистр eax используется для хранения значений, возвращаемых функцией для соглашения о вызовах stdcall.

leave

Инструкция leave в значительной степени является сокращением для

 movl ebp, esp
попл эбп

т.е. он «отменяет» все, что было сделано в начале функции - восстанавливает указатель кадра и стек в его прежнее состояние.

ret

Возвращает тому, кто вызвал эту функцию. Он вытолкнет указатель инструкции из стека (который будет помещен туда соответствующей инструкцией вызова) и перейдет туда.

56
ответ дан 7 November 2019 в 07:26
поделиться

Что касается и l $ -16,% esp

  • 32 бита: -16 в десятичном представлении равно 0xfffffff0 в шестнадцатеричном представлении
  • 64 бита: -16 в десятичном представлении равно 0xfffffffffffffff0 в шестнадцатеричном представлении

Таким образом, он замаскирует последние 4 бита ESP (между прочим: 2 ** 4 равно 16) и сохранит все остальные биты (независимо от того, является ли целевая система 32 или 64 бит).

__ main - это подпрограмма в стандартной библиотеке GNU, которая заботится о различных инициализациях при запуске. Это не является строго необходимым для программ на языке C, но требуется на тот случай, если код C связан с C ++.

_main - ваша основная подпрограмма. Поскольку и _main , и __ main являются местоположениями кода, они имеют одинаковый класс и тип хранилища. Я еще не нашел определения для .scl и .type . Вы можете получить некоторое освещение, определив несколько глобальных переменных.

Первые три инструкции устанавливают кадр стека, который является техническим термином для рабочего хранилища подпрограммы - по большей части локальных и временных переменных. Нажатие ebp сохраняет базу кадра стека вызывающего абонента. Ввод esp в ebp устанавливает основу нашего кадра стека. и выравнивают кадр стека по 16-байтовой границе на тот случай, если какие-либо локальные переменные в стеке требуют 16-байтового выравнивания (для инструкций x86 SIMD требуется такое выравнивание, но выравнивание действительно ускоряет обычные типы, такие как int s и float s.

На этом этапе обычно ожидается, что esp будет перемещен вниз в памяти, чтобы выделить пространство стека для локальных переменных. main не имеет ничего, поэтому gcc не беспокоит.

Вызов __ main является специальным для основной точки входа и обычно не появляется в подпрограммах.

Остальное идет, как вы и догадались .. Регистр eax - это место, куда можно поместить целочисленные коды возврата в двоичной спецификации. leave отменяет кадр стека, а ret возвращается к вызывающему. В этом случае вызывающей стороной является среда выполнения C нижнего уровня, которая будет выполнять дополнительную магию (например, вызывать функции atexit () , устанавливать код выхода для процесса и запрашивать у операционной системы завершение процесса.

12
ответ дан 7 November 2019 в 07:26
поделиться

В дополнение к и l $ -16,% esp , это работает, потому что установка младших битов на ноль всегда приводит к понижению % esp ] по значению, а стек растет вниз на x86.

4
ответ дан 7 November 2019 в 07:26
поделиться

У меня нет ответов на все, но я могу объяснить то, что знаю.

ebp используется функцией для сохранения начального состояния esp во время выполнения - ссылка на то, где аргументы передаются функции, а где - ее собственные локальные переменные. Первое, что делает функция, это сохраняет статус заданного ebp при выполнении pushl% ebp , это жизненно важно для функции, которая выполняет вызов, а затем заменяет его своим собственным текущая позиция в стеке esp выполнение movl% esp,% ebp . Обнуление последних 4 бит ebp на этом этапе зависит от GCC, я не знаю, почему этот компилятор это делает. Это сработало бы и без этого. Теперь, наконец, мы переходим к делу, звоним ___ main , кто __main? Я тоже не знаю ... возможно, больше процедур, специфичных для GCC, и, наконец, единственное, что делает ваш main (), устанавливает возвращаемое значение как 0 с помощью movl $ 0,% eax и leave , что аналогично выполнению movl% ebp,% esp; popl% ebp для восстановления состояния ebp , затем ret для завершения. ret pops eip и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .

По большей части это управление стеком. Некоторое время назад я написал подробное руководство о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...

установите возвращаемое значение как 0 с помощью movl $ 0,% eax и leave , что аналогично выполнению movl% ebp,% esp; popl% ebp для восстановления состояния ebp , затем ret для завершения. ret pops eip и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .

По большей части это управление стеком. Некоторое время назад я написал подробный учебник о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...

установите возвращаемое значение как 0 с помощью movl $ 0,% eax и leave , что аналогично выполнению movl% ebp,% esp; popl% ebp для восстановления состояния ebp , затем ret для завершения. ret pops eip и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .

По большей части это управление стеком. Некоторое время назад я написал подробное руководство о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...

ret pops eip и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .

По большей части это управление стеком. Некоторое время назад я написал подробное руководство о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...

ret pops eip и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .

По большей части это управление стеком. Некоторое время назад я написал подробный учебник о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...

2
ответ дан 7 November 2019 в 07:26
поделиться

Если я правильно помню, « * chrome » используется для запуска специального режима Firefox (режима, в котором ваше приложение имеет больше привилегии - с меньшими ограничениями безопасности) ; так что запускается именно Firefox, а не Google Chrome.

Если вы хотите запустить Google Chrome, вам нужно будет использовать что-то еще, кроме « * chrome ».


Использование Selenium RC в интерактивном режиме, примерно так:

$ java -jar selenium-server.jar -interactive

и неправильное использование команды getNewBrowserSession :

cmd=getNewBrowserSession

Я получил список поддерживаемых браузеров:

23:43:09.317 INFO - Got result: Failed to start new browser session: Browser not supported:
(Did you forget to add a *?)

Supported browsers include:
  *firefox
  *mock
  *firefoxproxy
  *pifirefox
  *chrome
  *iexploreproxy
  *iexplore
  *firefox3
  *safariproxy
  *googlechrome
  *konqueror
  *firefox2
  *safari
  *piiexplore
  *firefoxchrome
  *opera
  *iehta
  *custom
 on session null

Итак, я предполагаю , что вы сможете запускать Google Chrome, используя " * googlechrome " вместо " * chrome ".


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

В любом случае, получайте удовольствие!


Кстати: не Google Chrome изобрел термин «хром»; это означает много всего ,

5
ответ дан 7 November 2019 в 07:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: