информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
За кого нас держат?Все любят мед
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Крупный сбой Azure и других сервисов... 
 Серьезный сбой AWS положил множество... 
 Фишинговая атака на Python-разработчиков 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
а чего, примерно так оно всё и есть.. только написано как-то криво.. 14.05.04 16:15  Число просмотров: 1542
Автор: zelych Статус: Member
<"чистая" ссылка>
особенно не вчитывался, но по поводу что в какие сегменты кладётся - вроде правильно..

ЗЫЖ почему-то вспомнилась заморочка от макара:
чем отличается

void f()
{
char *str1 = "hello world";
// от
char str2[] = "hello world";
// ...
}
<programming>
[C++] посмотрите :)))) 14.05.04 14:58  
Автор: n013e Статус: Member
<"чистая" ссылка>
Сразу предупреждаю писал не я.

Методы обращения к данным

- при определении переменной интегрального типа вне функции
п-нная заносится в сегмент _BSS, обращение происходит посредством
прямой адресации памяти(например, byte ptr). инкрементирование значения
п-нной происходит через РОН.

если определить переменную вне функции с инициализацией начального
значения - п-нная заносится в _DATA.

при объявлении переменной внутри функции обращение п-нной
происходит как смещение относительно ebp, в котором находится
значение stack pointer`a для данной функции.

при объявлении глобальной переменной с модификатором volatile блок кода,
где используется данная переменная не оптимизируется

- массив

при объявлении массива вне функции без указания размерности добавляется модификатор
EXTRN, обращение к ячейкам массива происходит через идентификатор массива плюс смещение

в опт режиме цикл с обращениями к такому массиву раскладывается по отдельным итерациям.
(такая оптимизация происходит при малом значении итераций).

если объявить массив вне функции с указанием его длины, то массив помещается в сегмент
_BSS.

при объявлении указателя вне функции, ук-ль заносится в _BSS(в случае если этот ук-ль
не инициализируется или если ему присваивается значение оператора new). Если
присвоить указателю числовую константу - в _DATA. при обращении к ячейки памяти происходит
копирование значения указателя из памяти в регистр(например, есх или еах) и далее
запись/чтение через значение этого регистра с соответствующим сдвигом.

при объявлении массива без размерности в функции компилятор выдает ошибку. Если
инициализировать значение длины массива, то выделяется место в стеке (значение stack
pointer`a смещается на n*размер данных). при обращении к массиву используется
адресация по базе со смещением.

- поля структур

при объявлении структуры вне функции, она помещается в _BSS, если неинициализирована,
и в _DATA при задании начальных значений. в обоих случаях обращение к структуре
происходит посредством прямой адресации плюс смещение от начала структуры в зависимости
от поля. если структуру объявить с модификатором const, то она будет помещена в
CONST.

если структура объявлена внутри функции, то ст-ра размещается в стеке и обращение к полям
происходит относительно ebp.

при передаче структуры в качестве параметра через ссылку - передается
адрес(lea).

- члены классов

обращение к полям классов осуществляется так же как и к членам структур. при
вызове функций - членов классов, в качестве параметра неявно передается указатель this
(адрес объекта данного класса обычно заносится в регистр есх и передается в функцию
через этот регистр). конструктор в конце помещает в регистр еах значение this.

когда доступ к полю объекта осуществляется в функции(объект передается как параметр),
объект полностью кладется в стек в качестве аргумента(если объект объявлен внутри функции,
то при вызове функции происходит повторное копирование объекта в стеке, либо если
объект объявлен вне функции, то происходит копирование из _DATA либо _BSS в стек).
в функции обращение к полям относительно ebp.

при наличии виртуальных методов в классе, вначало каждого объекта помещается
адрес таблицы виртуальных методов(4 байта).
вызов виртуального метода:

- в регистр есх кладется адрес объекта(this).
- регистр(например, еах или еdх) заносится значение адреса ТВМ
и далее вызов ВМ командой call,

в данном случае (при наличии таблицы) первое поле объекта расположено за таблицей,
поэтому доступ к полю осуществляется с некоторым сдвигом от адреса объекта.
соответственно такое смещение не менее 4.
скажем, если имеется класс:

class base {
public:
char Char1;
virtual void Func1()
{
...
}
virtual void Func2()
{
...
}
};

то при обращении ко второму ВМ будет сгенерировано:

mov ecx, DWORD PTR _b$[ebp] ;адрес объекта в есх
mov edx, DWORD PTR [ecx] ;первые 4 байта (адрес ТВМ) в edx
mov ecx, DWORD PTR _b$[ebp] ;this в ecx
call DWORD PTR [edx+4] ;вызов виртуального метода,
;т.к. метод второй то смещение в таблице 4

далее, при обращении к полю Char1

mov eax, DWORD PTR _b$[ebp] ;адрес объекта в есх
mov BYTE PTR [eax+4], 78 ;заносим значение в байт (адрес объекта+4),
;(с учетом ТВМ)

если определить класс как:
class base {
public:
char Char1;

};

то оператор sizeof возвратит значение 1.
если :
class base {
public:
char Char1;
virtual void Func1()
{
...
}
virtual void Func2()
{
...
}
};
то sizeof возвратит 8.

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


P.S. писал не я
а чего, примерно так оно всё и есть.. только написано как-то криво.. 14.05.04 16:15  
Автор: zelych Статус: Member
<"чистая" ссылка>
особенно не вчитывался, но по поводу что в какие сегменты кладётся - вроде правильно..

ЗЫЖ почему-то вспомнилась заморочка от макара:
чем отличается

void f()
{
char *str1 = "hello world";
// от
char str2[] = "hello world";
// ...
}
это и есть фишка от макара... ромина пятая лаба... он просто... 14.05.04 22:04  
Автор: n013e Статус: Member
<"чистая" ссылка>
это и есть фишка от макара... ромина пятая лаба... он просто писал этот отчёт будучи под воздествием веществ, искажающих его восприятие мира..... макар его минут 20 распекал, что рома писать не умет :), он обиделся и попросил что-бы его художества оценили :)
... 21.05.04 00:25  
Автор: chill Статус: Незарегистрированный пользователь
<"чистая" ссылка>
> это и есть фишка от макара... ромина пятая лаба... он
> просто писал этот отчёт будучи под воздествием веществ,
> искажающих его восприятие мира..... макар его минут 20
> распекал, что рома писать не умет :), он обиделся и /|\
> попросил что-бы его художества оценили :) |
|
прошу принять во внимание при прочтении сего сообщения | следующие несколько фактов, которые
не были указаны достопочтеннейшим г-ном noiZe, но которые стоят того, чтобы их изложили:
1. прежде всего это то, что все имена вымышлены. Таких людей (рома,макар) никогда не существовало
на планете Земля и всякое сходство является только случайностью и не более того.
2. хим вещества не являются чем то противоречащим конституции и законодательству РФ
3. никакой рома не обижался никакого макара (прошу особо отметить этот пункт).
Здесь-то под многими системами разницы не будет ни какой,... 14.05.04 16:47  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> особенно не вчитывался, но по поводу что в какие сегменты
> кладётся - вроде правильно..
>
> ЗЫЖ почему-то вспомнилась заморочка от макара:
> чем отличается
>
> void f()
> {
> char *str1 = "hello world";
> // от
> char str2[] = "hello world";
> // ...
> }
Здесь-то под многими системами разницы не будет ни какой, правда под Линуксом возникнет ошибка во время выполнения если написать str1[ 0 ] = 'H', а при выполнении str2[ 0 ] = 'H' ошибки не возникнет.
Раз уж зашла тема про массивы и указатели, напишу про один вопросик, который до сих пор не разрешен и покоя мне не дает. В двух разных модулях используется один массив, в одном описан, в другом определен:
char str[] = "hello, world.";
в одном, а в другом
extern char *str;
Причем, естественно extern может присутствовать в первом, и, естественно, отсутствовать во втором. Работа с массивом компилироваться должна с точки зрения языка одиннаково исходя из равнозначности описания и по разному исходя из здравого смысла. А именно оператор *str = 'H' должен дать разные коды для корректной работы.
1)
lea bx, str
mov byte ptr[bx], 'H'
или
mov bx, offset str
mov byte ptr[bx], 'H'
или
mov al, 'H'
mov str, al
если str определен как
str db 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.', 0
или
str label byte
db 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.', 0
2)
mov bx, str
mov byte ptr[bx], 'H'
если str описан как
str dw tmp
tmp db 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.', 0

Неоднозначность какая-то имеет место быть по-моему...
не, у загадки есть более интерестное решение.. 15.05.04 00:50  
Автор: zelych Статус: Member
<"чистая" ссылка>

...
> дает. В двух разных модулях используется один массив, в
> одном описан, в другом определен:
> char str[] = "hello, world.";
> в одном, а в другом
> extern char *str;
> Причем, естественно extern может присутствовать в первом,
> и, естественно, отсутствовать во втором. Работа с массивом

может я чего не понял, но, кажется, компилятор не даст написать
extern char str[] = "...";
да и в первом случае, строка будет лежать в сегменте констант, поэтому
*str = 'H';
делать нельзя.. разве что в досе только..
хотя надо попробовать..

> Неоднозначность какая-то имеет место быть по-моему...
собственно, отгадка.. 19.05.04 16:22  
Автор: zelych Статус: Member
<"чистая" ссылка>
много писать не буду, поскольку никто слишком не интересовался..

f1() () at c.cpp:5 5 char str[] = "hello world?????"; (gdb) disassemble Dump of assembler code for function _Z2f1v: 0x8048300 <_Z2f1v>: push %ebp 0x8048301 <_Z2f1v+1>: mov %esp,%ebp 0x8048303 <_Z2f1v+3>: push %edi 0x8048304 <_Z2f1v+4>: push %esi 0x8048305 <_Z2f1v+5>: sub $0x20,%esp 0x8048308 <_Z2f1v+8>: lea 0xffffffd8(%ebp),%edi 0x804830b <_Z2f1v+11>: mov $0x804845c,%esi 0x8048310 <_Z2f1v+16>: cld 0x8048311 <_Z2f1v+17>: mov $0x11,%ecx 0x8048316 <_Z2f1v+22>: repz movsb %ds:(%esi),%es:(%edi) 0x8048318 <_Z2f1v+24>: add $0x20,%esp 0x804831b <_Z2f1v+27>: pop %esi 0x804831c <_Z2f1v+28>: pop %edi 0x804831d <_Z2f1v+29>: leave 0x804831e <_Z2f1v+30>: ret End of assembler dump. (gdb) x/s 0x804845c 0x804845c <_IO_stdin_used+4>: "hello world?????" 10 char *str = "hello world!!!!!"; (gdb) disassemble Dump of assembler code for function _Z2f2v: 0x8048320 <_Z2f2v>: push %ebp 0x8048321 <_Z2f2v+1>: mov %esp,%ebp 0x8048323 <_Z2f2v+3>: sub $0x4,%esp 0x8048326 <_Z2f2v+6>: movl $0x804846d,0xfffffffc(%ebp) 0x804832d <_Z2f2v+13>: leave 0x804832e <_Z2f2v+14>: ret End of assembler dump. (gdb) x/s 0x804846d 0x804846d <_IO_stdin_used+21>: "hello world!!!!!"

если кто ещё не понял - разница принципиальная..
если у вас в цикле много раз вызывается функция с такой вот строчкой:

char str[] = "very very long string";

то это не есть хорошо
Ну да, естественно, не будем инициализировать внешний... 17.05.04 12:27  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> может я чего не понял, но, кажется, компилятор не даст
> написать
> extern char str[] = "...";
Ну да, естественно, не будем инициализировать внешний массив. Смысл в том, чтоб внешним был не указатель а массив. Пусть будет просто extern char str[ 1 ]; ничто не мешает в другом модуле обратиться к последующим элементам.
> да и в первом случае, строка будет лежать в сегменте
> констант, поэтому
> *str = 'H';
> делать нельзя.. разве что в досе только..
Ну не писать, а читать. Пусть будет printf( "%c", *str );
> хотя надо попробовать..
>
> > Неоднозначность какая-то имеет место быть по-моему...
забавный эффект получается.. 19.05.04 16:14  
Автор: zelych Статус: Member
<"чистая" ссылка>
если взять два файлика:
--- a.c ---
#include <stdio.>

extern char str[];

void main()
{
    puts( str );
}

--- b.c ---
char *str = "hello world"


---
то в качестве аргумента puts передаётся адрес указателя на строку:
0x8048343 <main+19>:    push   $0x8049474
0x8048348 <main+24>:    call   0x8048254 <puts>
...
(gdb) x 0x8049474
0x8049474 <str>:        0x0804845c
(gdb) x/s 0x804845c
0x804845c <_IO_stdin_used+4>:    "hello world"

---

соответственно, печатается не hello world, а мусор..
если в b.c написать str[] = "hello world", тогда всё окей, выводится сама строка..
и наоборот, тобишь тип должен быть одинаковым в обеих файлах..

вопрос! почему тогда компилятор не ругается на несоответствие типов?
испытания проводились под gcc, выжалстудию, и интеловский компилятор.. результат одинаковый
Ну я примеры не приводил, а только описал. В том-то и дело,... 20.05.04 14:30  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 20.05.04 14:31  Количество правок: 1
<"чистая" ссылка>
> соответственно, печатается не hello world, а мусор..
> если в b.c написать str[] = "hello world", тогда всё окей,
> выводится сама строка..
> и наоборот, тобишь тип должен быть одинаковым в обеих
> файлах..
>
> вопрос! почему тогда компилятор не ругается на
> несоответствие типов?
> испытания проводились под gcc, выжалстудию, и интеловский
> компилятор.. результат одинаковый

Ну я примеры не приводил, а только описал их. В том-то и дело, что везде описано, что str[] и *str идентичны! А на деле-то совсем не так. Мало того и не может быть так. Ну а не ругается, потому что по правилам языка типы то соответствуют.
непонятно как-то.. 20.05.04 15:44  
Автор: zelych Статус: Member
<"чистая" ссылка>

> Ну я примеры не приводил, а только описал их. В том-то и
> дело, что везде описано, что str[] и *str идентичны! А на

в том-то и дело, что не идентичны..
то, что описано в другом моём посте - это в соответствии со стандартом


> деле-то совсем не так. Мало того и не может быть так. Ну а
> не ругается, потому что по правилам языка типы то
> соответствуют.

просто какое-то не совсем логичное поведение компиляторов..

http://www.bugtraq.ru/cgi-bin/forum.mcgi?type=sb&b=2&m=104939
И я говорю, что на практике не идентичны, а в соответствии... 20.05.04 16:29  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> в том-то и дело, что не идентичны..
> то, что описано в другом моём посте - это в соответствии со
> стандартом

И я говорю, что на практике не идентичны, а в соответствии со стандартом должны быть идентичны.

> просто какое-то не совсем логичное поведение компиляторов.

Как же не логичное. Компиляторы генерят код по описанию. Просто в стандарте надо указать, что *str и str[] совершенно разные вещи! Только для удобства программеров сделано так, что обращение к элементам по *str и str[ 0 ] эквивалентны, как и циклическая обработка векторов по *str++ и str[ i++ ], где, разумеется, в первом случае изменяется сам указатель, а во втором только индекс, и, опять же, первая конструкция совсем не применима, если str был описан как массив, а не указатель.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2025 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach