Форум программистов, компьютерный форум, киберфорум
C++: WinAPI
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/21: Рейтинг темы: голосов - 21, средняя оценка - 5.00
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
1

Узнать сколько байт занимает инструкция функции

17.06.2021, 16:30. Показов 4266. Ответов 22
Метки нет (Все метки)

Предположим есть функции
C++
1
2
3
4
int puk(){cout<<"funr "<<puk<<en;
ret 942;}
int pul(){cout<<"funr "<<puk<<en;
ret 94267;}
расстояние между ними 75 байт, мне нужно получить этот размер. Пробовал проходить эти байты указателями но они плотно упакованы, что в принципе понятно. Я думал может там есть по 4 байта по краям как это бывает с другими элементам например со структурами(хотя это худший пример), но никакого выравнивания и никаких таких пустых ячеек там нет. Может есть какие функции это вычисляющие.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.06.2021, 16:30
Ответы с готовыми решениями:

Как определить, сколько байт занимает массив?
Как определить сколько байт занимает массив? Приведите фрагмент кода, с помощью которого можно это...

Как узнать, в процесе отладки, сколько памяти занимает программа?
Вот чтобы проследить за тем сколько и когда программа занимает и какое количество килобайт под...

Как узнать, сколько памяти занимает тот или иной элемент программы?
Товарищи, подскажите, пожалуйста, ответы на следующие вопросы: 1) Есть какие-либо средства...

Сколько байт занимает макрос?
Подскажите, пожалуйста, сколько байт занимает макрос?;макрос PrintString macro str local...

22
1097 / 1006 / 152
Регистрация: 19.02.2010
Сообщений: 3,082
17.06.2021, 17:34 2
Про отдельные процессорные инструкции (сколько они занимают в байтах) - в интеловском справочнике Instruction Set Reference по системе команд интел-совместимых процессоров.
Расстояние же между функциями - легко можно посчитать с помощью указателей на функции (через разность значений этих указателей - через разность хранящихся в указателях адресов).
0
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
17.06.2021, 18:20 3
Цитата Сообщение от Nexi99 Посмотреть сообщение
между ними 75 байт, мне нужно получить этот размер
Nexi99, для чего это Вам нужно, если не секрет?

Цитата Сообщение от Nexi99 Посмотреть сообщение
никакого выравнивания и никаких таких пустых ячеек там нет
Нередко есть выравнивание на какую-то зависящую от платформы границу:
Кликните здесь для просмотра всего текста
?puk@@YAHXZ:
Код
  00000001400017F4: 48 83 EC 28        sub         rsp,28h
  00000001400017F8: 48 8D 15 B1 63 00  lea         rdx,[140007BB0h]
                    00
  00000001400017FF: 48 8B 0D D2 98 00  mov         rcx,qword ptr [__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A]
                    00
  0000000140001806: E8 27 F8 FF FF     call        @ILT+45(??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z)
  000000014000180B: 48 8D 15 AC F8 FF  lea         rdx,[@ILT+185(?puk@@YAHXZ)]
                    FF
  0000000140001812: 48 8B C8           mov         rcx,rax
  0000000140001815: FF 15 CD 98 00 00  call        qword ptr [__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z]
  000000014000181B: B2 0A              mov         dl,0Ah
  000000014000181D: 48 8B C8           mov         rcx,rax
  0000000140001820: E8 52 F9 FF FF     call        @ILT+370(??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z)
  0000000140001825: B8 AE 03 00 00     mov         eax,3AEh
  000000014000182A: 48 83 C4 28        add         rsp,28h
  000000014000182E: C3                 ret
000000014000182F: CC int 3
0000000140001830: CC int 3
0000000140001831: CC int 3
0000000140001832: CC int 3
0000000140001833: CC int 3
0000000140001834: CC int 3
0000000140001835: CC int 3
0000000140001836: CC int 3
0000000140001837: CC int 3

?pul@@YAHXZ:
Код
  0000000140001838: 48 83 EC 28        sub         rsp,28h
  000000014000183C: 48 8D 15 75 63 00  lea         rdx,[140007BB8h]
                    00
  0000000140001843: 48 8B 0D 8E 98 00  mov         rcx,qword ptr [__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A]
                    00
  000000014000184A: E8 E3 F7 FF FF     call        @ILT+45(??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z)
  000000014000184F: 48 8D 15 68 F8 FF  lea         rdx,[@ILT+185(?puk@@YAHXZ)]
                    FF
  0000000140001856: 48 8B C8           mov         rcx,rax
  0000000140001859: FF 15 89 98 00 00  call        qword ptr [__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z]
  000000014000185F: B2 0A              mov         dl,0Ah
  0000000140001861: 48 8B C8           mov         rcx,rax
  0000000140001864: E8 0E F9 FF FF     call        @ILT+370(??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z)
  0000000140001869: B8 3B 70 01 00     mov         eax,1703Bh
  000000014000186E: 48 83 C4 28        add         rsp,28h
  0000000140001872: C3                 ret
0
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
17.06.2021, 18:41  [ТС] 4
Цитата Сообщение от VTsaregorodtsev Посмотреть сообщение
Расстояние же между функциями - легко можно посчитать с помощью указателей на функции (через разность значений этих указателей - через разность хранящихся в указателях адресов).
Да но я же не могу пихать указатель после каждой функции, или зачем мне присваивать а потом считать, мне нужно знать это сразу, чтобы считать 10ть 20ть функций и автоматом загрузить адреса в массив указателей к примеру.

Добавлено через 2 минуты
Цитата Сообщение от VTsaregorodtsev Посмотреть сообщение
Про отдельные процессорные инструкции (сколько они занимают в байтах) - в интеловском справочнике Instruction Set Reference по системе команд интел-совместимых процессоров.
В Ассемблере указывается сколько отступить и т.д., я думал может это дело регистрируется, да и к тому же много кому интересно узнать сколько памяти занимает код функции.
0
797 / 298 / 57
Регистрация: 20.11.2012
Сообщений: 665
17.06.2021, 18:42 5
Слишком мало информации, как всегда. Напиши, зачем тебе это нужно - исходя из этого люди подскажут.
В общем случае можно вычесть адреса функций pul-puk, но есть много но. Например, функции что ты привел как пример - скорее всего будут заинлайнены оптимизатором, т.е. функций как таковых вообще не будет.
0
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
17.06.2021, 18:48  [ТС] 6
Цитата Сообщение от WhiteP Посмотреть сообщение
В общем случае можно вычесть адреса функций pul-puk, но есть много но. Например, функции что ты привел как пример - скорее всего будут заинлайнены оптимизатором, т.е. функций как таковых вообще не будет.
Я не могу их вычесть, я хочу прочитать всё разом. У меня 32 битный оптимизатор он не сможет их заинлайнить да и к тому же указатели на эти функции будут созданы(а это означает отмену инлайна, раз есть указатель, есть вызов функции, а если есть её вызов то компилятор обязан построить инструкцию и процессор обязан смотреть на указатель в моём случае, но в вашем может быть и по другому), а я хочу прочитать память одним махом.
0
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
17.06.2021, 18:56 7
Наличие указателей на функции не мешает их инлайнить.
0
797 / 298 / 57
Регистрация: 20.11.2012
Сообщений: 665
17.06.2021, 19:09 8
Цитата Сообщение от Nexi99 Посмотреть сообщение
а это означает отмену инлайна, раз есть указатель, есть вызов функции, а если есть её вызов то компилятор обязан построить инструкцию и процессор обязан смотреть на указатель в моём случае
Тут все зависит от того ЗАЧЕМ тебе это нужно. Куда ты хочешь их прочитать? Что с ними потом делать? Не нужно секретных подробностей, просто пример. Уточни, чтобы не гадать.
Может быть по всякому. Вот для примера ниже функции сгенерированы, но по факту они не вызываются.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
int a()
{
    std::cout << "a func" << std::endl;
    return 1;
}
 
int b()
{
    std::cout << "b func" << std::endl;
    return 2;
}
 
int main(int argc, char** argv)
{
    a();
    b();
    std::cout <<a <<std::endl;
    std::cout << b << std::endl;
    return 0;
}
0
Миниатюры
Узнать сколько байт занимает инструкция функции  
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
17.06.2021, 19:58 9
И компилятор не может не сгенерировать код. Потому что a() и b() доступны в других единицах трансляции, в которых их исходное определение не видно.

Добавлено через 25 минут
Цитата Сообщение от Nexi99 Посмотреть сообщение
В Ассемблере указывается сколько отступить и т.д., я думал может это дело регистрируется
Ассемблер тут ни при чём.
А в объектом файле - результате компиляции единицы трансляции, все определённые и использованные внешние символы регистрируются. Чтобы при компоновке можно было связать раздельно комилированные модули.
C
1
2
3
int     a(), b(), puk(), pul();
 
void* funcaddr[] = { a, b, puk, pul };
Windows Batch file
1
cl /c usepuab.c /nologo & link /dump /symbols usepuab.obj /nologo
Код
usepuab.c

Dump of file usepuab.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 010474D9 ABS    notype       Static       | @comp.id
001 80010190 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length   70, #relocs    0, #linenums    0, checksum        0
006 00000000 UNDEF  notype ()    External     | a
007 00000000 UNDEF  notype ()    External     | b
008 00000000 UNDEF  notype ()    External     | puk
009 00000000 UNDEF  notype ()    External     | pul
00A 00000000 SECT3  notype       Static       | .data
    Section length   20, #relocs    4, #linenums    0, checksum        0
00C 00000000 SECT3  notype       External     | funcaddr
00D 00000000 SECT4  notype       Static       | .chks64
    Section length   20, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x0 bytes

  Summary

          20 .chks64
          20 .data
          70 .debug$S
          2F .drectve
Windows Batch file
1
link /dump /symbols pu.obj | findstr /r pu[kl]
Код
3C6 00000000 SECT4  notype ()    External     | ?puk@@YAHXZ (int __cdecl puk(void))
3D1 00000040 SECT4  notype ()    External     | ?pul@@YAHXZ (int __cdecl pul(void))
9AF 00000000 SECT2D2 notype       Static      | $unwind$?puk@@YAHXZ
9B2 00000000 SECT2D3 notype       Static      | $pdata$?puk@@YAHXZ
A58 00000008 SECT2D2 notype       Static      | $unwind$?pul@@YAHXZ
A59 0000000C SECT2D3 notype       Static      | $pdata$?pul@@YAHXZ
У компоновщика можно попросить карту построенного исполняемого модуля:
Windows Batch file
1
cl /EHsc /Os /nologo pu.cpp /link /map:pu.map & findstr /r pu[kl] pu.map
Код
 0001:00000140       ?puk@@YAHXZ                0000000140001140 f   pu.obj
 0001:00000180       ?pul@@YAHXZ                0000000140001180 f   pu.obj
 0002:0000ff38       $unwind$?puk@@YAHXZ        000000014003cf38     pu.obj
 0002:0000ff40       $unwind$?pul@@YAHXZ        000000014003cf40     pu.obj
Но в самом модуле информации об именах функций не будет, если они не экспортируются.
Имена и адреса неэкспортируемых функций могут быть в таблицах отладочной информации для отладчика. /DEBUG
0
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
17.06.2021, 21:21  [ТС] 10
Цитата Сообщение от WhiteP Посмотреть сообщение
Тут все зависит от того ЗАЧЕМ тебе это нужно.
Получаем адрес функции а по вашему примеру пишем её в массив указателей, далее получаем размер инструкции в байтах, перепрыгиваем на функцию b пишем её в массив, далее получаем размер инструкции в байтах, перепрыгиваем на след. функцию и так собираем все функции. Ну типа динамическая сборка а не константная когда пишешь присвоить. Ну это пример конечно, могут быть и другие.

Добавлено через 1 минуту
Цитата Сообщение от WhiteP Посмотреть сообщение
Вот для примера ниже функции сгенерированы, но по факту они не вызываются.
Мне ваша миниатюрка понравилась https://www.cyberforum.ru/atta... 1623945766

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

Добавлено через 20 минут
Цитата Сообщение от WhiteP Посмотреть сообщение
ниже функции
сколько байт в коде занимает выполнить инструкцию mov?
0
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
17.06.2021, 22:37 11
Цитата Сообщение от Nexi99
Получаем адрес функции а по вашему примеру пишем её в массив указателей, далее получаем размер инструкции в байтах, перепрыгиваем на функцию b пишем её в массив, далее получаем размер инструкции в байтах, перепрыгиваем на след. функцию и так собираем все функции.
Вы хотите сгенерировать код функции налету?
0
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
17.06.2021, 23:11  [ТС] 12
Цитата Сообщение от politoto Посмотреть сообщение
Вы хотите сгенерировать код функции налету?
Нет пройти его налету. Вот нашёл объяснение что команда mov 4 байта.
C++
1
9     0107  8A 26 0103r                MOV    AH,byte ptr flddb
9 - номер строки
0107 - смещение (адрес) текущей строки
8A 26 0103r - байты (машинный код), полученные после трансляции команды
MOV AH,byte ptr flddb - сама команда
В данном случае для меня проще сразу посмотреть количество байт: 8A 26 0103r - это 8 шестнадцатеричных цифр (r не считается), делим на 2 (по две цифры на байт), получаем 4 (1 байт - 8 бит, 1 шестнадцатеричная цифра кодирует 4 бита, отсюда 2 цифры на байт).

Другой способ - смотрим разницу смещений соседних строк. Пример:

C++
1
2
3
  
  9     0107  8A 26 0103r                MOV    AH,byte ptr flddb
10     010B  32 F6                      XOR    DH,DH
Разница 010B - 0107 = 4, что соответствует тому что мы получили выше, просто посчитав байты. Я считаю, что посчитать байты (если их немного) все-таки проще, чем в уме считать в шестнадцатеричной системе. Но не всегда в листинге присутствует колонка с машинным представлением команд, в таких случаях приходится считать разницу смещений.

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

Добавлено через 1 минуту
Хотя и налету можно генерировать учитывая происходящее но это будет очень тяжело сделать, да и мне это не нужно.
0
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
18.06.2021, 08:51 13
Допустим, мы знаем сколько байтов занимают инструкции в одной функции:
Windows Batch file
1
cl /c /Faconout$ /FAsc m.c /nologo
Код
; 5    : int b() {
  00000 55               push    ebp
  00001 8b ec            mov     ebp, esp
; 6    :        return 0100000000;
  00003 b8 00 00 00 01   mov     eax, 16777216          ; 01000000H
; 7    : }
  00008 5d               pop     ebp
  00009 c3               ret     0
и в другой
Код
; 1    : int a() {
  00000 55               push    ebp
  00001 8b ec            mov     ebp, esp
; 2    :        return -1;
  00003 83 c8 ff         or      eax, -1
; 3    : }
  00006 5d               pop     ebp
  00007 c3               ret     0
Как можно это знание использовать?
0
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
18.06.2021, 10:15  [ТС] 14
Цитата Сообщение от politoto Посмотреть сообщение
Допустим, мы знаем сколько байтов занимают инструкции в одной функции:
Можно перепрыгивать с одной функции на другую, если знать какой бинарный код и где записан можно даже поменять его налету например стереть первую команду у функции
C++
1
00000 55               push    ebp
Если это конечно возможно и не меняет логику функции, а те байты просто сдвинуть, для тех кто лучше в этом разбирается можно оптимизировать код. Мне же нужно иметь возможность перепрыгивать между функциями чтобы быстро составить массив указателей на функции но узнать размер инструкции нельзя.
0
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
18.06.2021, 10:34 15
Так разве не быстро? Вы же знаете точки входа в функции, а длина их кода не нужна.
C
1
2
3
const char a[] = {0270,0,0,0,1, 0303}, b[4] = {"\x83\310\377\303"};
 
const void * functions[] = { a, b, };
Компилятор и сам неплохо оптимизирует, если попросить.
Попросишь короче, сделает короче:
Windows Batch file
1
cl /c /O1 /Faconout$ /FAsc  m.c /nologo
Код
_b      PROC                                            ; COMDAT
; 6    :        return 0100000000;
  00000 b8 00 00 00 01   mov     eax, 16777216          ; 01000000H
; 7    : }
  00005 c3               ret     0
_b      ENDP

_a      PROC                                            ; COMDAT
; 2    :        return -1;
  00000 83 c8 ff         or      eax, -1
; 3    : }
  00003 c3               ret     0
_a      ENDP
0
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
18.06.2021, 10:44  [ТС] 16
Цитата Сообщение от politoto Посмотреть сообщение
Так разве не быстро?
Ну речь идёт об избавлении от констант, о создании универсальных и динамических алгоритмов, и если к примеру мы знаем размер инструкции можно прогнать цикл по нужным адресам и собрать это всё в один массив и не нужно писать что-то вроде
C++
1
const void * functions[] = { a, b, };
0
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
18.06.2021, 10:51 17
Массив собирается во время компиляции. Когда программа работает, массив уже готов и гонять циклы не нужно.

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

Цитата Сообщение от Nexi99 Посмотреть сообщение
о создании универсальных и динамических алгоритмов
Во время компиляции алгоритмы неизвестны?
0
134 / 19 / 2
Регистрация: 06.05.2019
Сообщений: 1,263
Записей в блоге: 3
18.06.2021, 10:52  [ТС] 18
Цитата Сообщение от politoto Посмотреть сообщение
Во время компиляции алгоритмы неизвестны?
но известна специфика действий. Хотя на этим тоже стоит задуматься. Иногда речь идёт о уже составленном коде например dll.
Цитата Сообщение от politoto Посмотреть сообщение
Попросишь короче, сделает короче:
а где можно получить полностью ассемблерный код, я здесь смотрю https://godbolt.org/ но там не такой код как у вас и часто оптимизатор выбрасывает код, я конечно понимаю почему но просто иногда хочется увидеть любой алгоритм на ассемблере чтобы сделать выводы стоит ли оставить текущий или написать другой.
0
Модератор
1273 / 703 / 131
Регистрация: 23.07.2018
Сообщений: 2,323
Записей в блоге: 3
18.06.2021, 11:24 19
Там самый ранний - MSVC 2015. Можно отключить Demangle в настройках Output и наблюдать, как различные опции компилятора /O1 или /O2 влияют на результат.
https://godbolt.org/z/YnGbvKonx

Чтобы получить листинг от Вашего MSVC, нужно добавить флажок /Fa.
Можно добавить ещё /FAsc, чтобы увидет подробности с комментариями.

В Visual Studio включить выдачу листинга можно на странице C++/Выходные файлы свойств исходника.
https://docs.microsoft.com/ru-... sting-file
0
797 / 298 / 57
Регистрация: 20.11.2012
Сообщений: 665
18.06.2021, 13:04 20
Короче я снова мало чего понял.
politoto, вы по видимому понимаете?
Nexi99, если ты планируешь копировать функции побайтово с целью дальнейшего запуска этих байт - то все не так просто. Релоки, относительные смещения, выравнивание стека в зависимости от calling convention и т.д. и т.п.
Отвечая на вопрос из сабжа - простым способом и на 100% достоверно для всех исполняемых файлов - никак. Можно провести дизассемблирование, глубокий анализ с построением графа перекрестных ссылок из всех call/ret, учесть потенциальные инструкции пролога/эпилога функций, инлайны выявить по дублированию. Опираясь на эти данные - считать размер функций. Но тут и IDA ошибается порою...
То есть универсального простого способа нет. Примерно - самым очевидным вычитанием указателей на функции.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.06.2021, 13:04

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Сколько байт занимает символ и почему?
Добрый день, уважаемые форумчане. Всем известно что sizeof(char) == 1 .Заметил, что...

Сколько байт занимает один символ BigInteger?
Думаю, для записи одной цифры достаточно 4 бита. Но так ли это в BigInteger? Сколько байт/бит...

Сколько байт и почему занимает сегмент данных программы?
Подскажите пожалуйста сколько байт и почему занимает сегмент данных программы?; символ пробела...

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

Узнать сколько занимает файл на диске
Здравствуйте! Нужно узнать сколько места занимает файл. Но не просто объем самого файла, а объем...

Узнать сколько занимает памяти объект.
Здравствуйте. Кто нибудь в курсе, как можно узнать сколько &quot;весит&quot; экземпляр написанного мной...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.