Прежде всего, спасибо, что взорвал мой разум.Когда я впервые посмотрел на ваш код, я не верил, что он вообще сработает.Тогда я попробовал и воспроизвел ваши результаты.Теперь это имеет смысл для меня, хотя и в искаженном виде.:-) Я попытаюсь объяснить это.
Во-первых, давайте посмотрим на более разумный способ добиться этого.Определите строку в части данных файла ASM:
section .data
string: db "Hey, is this thing on?", 0
Затем поместите адрес этой строки в стек перед вызовом printf:
push string
call printf
Итак, этот первый параметр дляprintf (последний параметр, помещаемый в стек перед вызовом) - указатель на строку формата.То, что сделал ваш код, это поместил строку в стек, а затем указатель стека, который затем указал на строку.
Далее я собираюсь заменить ваши строки, чтобы их было легче отслеживать при разборке:
push '567'
push '123'
push esp
call printf
Соберите с помощью nasm, а затем разберите с помощью objdump:
nasm string.s -f elf32 -o string.o
objdump -d -Mintel string.o
Когда вы нажимаете, например, «123», это преобразуется в 32-разрядную шестнадцатеричную цифру:0x333231 в этом случае.Обратите внимание, что полные 32 бита равны 0x00333231.
3: 68 35 36 37 00 push 0x373635
8: 68 31 32 33 00 push 0x333231
d: 54 push esp
Вставка в стек уменьшает указатель стека.Предполагая начальный указатель стека 0x70 (придуманный для простоты), это состояние стека перед вызовом printf:
64: 68: 6c: 70:
68 00 00 00 31 32 33 00 35 36 37 00 ...
Итак, когда вызывается print, он использует первый параметр в качестве указателя строки иначинает печатать символы до тех пор, пока не увидит NULL (0x00).
Вот почему в этом примере выводится только «123» («sud» в вашем оригинале).
Так что давайте нажимаем «1234» вместо"123".Это означает, что мы выдвигаем значение 0x34333231.При вызове printf стек теперь выглядит следующим образом:
64: 68: 6c: 70:
68 00 00 00 31 32 33 34 35 36 37 00 ...
Теперь между этими двумя строками в стеке нет пропуска NULL, и в этом примере будет напечатано «1234567» (или «sudobor» в оригинале).1030 *
Последствия: попробуйте нажать «5678» вместо «567».Вы, вероятно, получите ошибку сегментации, потому что printf будет просто читать символы для печати, пока не попытается прочитать память, у которой нет разрешения на чтение.Также попробуйте нажать строку длиной более 4 символов (например, «push '12345'»).Ассемблер не позволит вам, потому что он не может преобразовать это в 32-битное число.