Форум программистов, компьютерный форум, киберфорум
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.72/229: Рейтинг темы: голосов - 229, средняя оценка - 4.72
4 / 3 / 0
Регистрация: 03.05.2009
Сообщений: 82

До слез Хочу научится Ассемблеру!!!

03.05.2009, 19:25. Показов 48661. Ответов 112
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Хочу научится Ассемблеру!!! С чего начать? Пока читаю Калашникова но не умею работать на МАСМе там всё на английском. Есть ли русская версия или руссификатор?
Английский у меня не очень... у калашникова говорится что надо умет шарит на DOS
и на Нортоне а где взять их Я все учебники самоучители скачала со всех библиотек в интернете но пока о нортоне ничего не нашла кроме как на Википедии Прошу помоч
разобратся.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.05.2009, 19:25
Ответы с готовыми решениями:

Хочу научится программированию
Хочу научится программированию .NET Может ктото подскажет с чего начать, обучаюсь очень быстро, знаю PHP, MySQL, Visual C++ 6.0, Pascal, ...

Хочу научится программировать
Здравствуйте! Не знал в какую тему написать, но в данном случае мне нужно что-то на подобии алгоритма. Я хочу самостоятельно научиться...

Хочу научится веб дизайну
Хочу научится веб дизайну. Но я не знаю своих ошибок в работе, а книги и курсы ответов уже не дают. Главный вопрос... Наверное,...

112
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
19.07.2009, 02:20
Студворк — интернет-сервис помощи студентам
Evg, ясно Есть хорошая фраза: можно изучить язык программирования за 3 дня, а научиться на нем программировать только за 3 года.
2
Anthony
19.07.2009, 09:11
Sayfera русскому языку для начала научись.
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
19.07.2009, 14:55
Лучший ответ Сообщение было отмечено как решение

Решение

**

Добавлено через 2 часа 2 минуты 58 секунд
Попробую ещё раз разложить всё по полочкам и изложить доступно.

======================================== ================

Для начала касаемо тех, кто "выучил ассемблер". За народной мудростью в этом отношении ходить далеко не надо - оно чуть выше:

Цитата Сообщение от Vourhey Посмотреть сообщение
Есть хорошая фраза: можно изучить язык программирования за 3 дня, а научиться на нем программировать только за 3 года.
Да, уметь делать хоть что-то на ассемблере оно очень полезно. Хотя бы потому, что появляется некое представление о том, как работает машина. Но писать на ассемблере программы из разряда "найти максимальный элемент массива" - это только для приобретения навыков и не более того. Да и то, навыки эти оказываются не полноценно полезными, т.к. класс решаемых на ассемблере задач несколько другой. А задачи, подобные приведённой, нужно решать на языках программирования.

Одного "знания ассемблера" явно недостаточно в тех случаях, когда программирование на ассемблере является объективной необходимостью. В качестве примера хочется привести эту тему. Не для того, чтобы похвастаться, а для того, чтобы продемоснтировать выше сказанное на конкретном примере. Автор "знал ассемблер", но я сильно подозреваю, что общий принцип был почерпан из книги или лекций. Т.е. проблема автора была в том, что у него не было чёткого представления, как на самом деле работает машина. Ну и сказывалась нехватка опыта в отладке программ. Это скорее дополнительная демонстрация к этой теме, потому как для планировщика задач мы имели задачу, которую впринципе нельзя запустить из-под отладчика.

С моей же стороны было практически нулевое знание интеловского ассемблера, практически нулевые знания того, как всё это дело работает под DOS'ом. Но у меня имелись общие знания того, как устроен процесс переключения задач в операционных системах. И эти знания оказались более важными. В итоге я целую неделю добивался от товарища, чтобы он мне рассказал, что и как у него делается. Так много времени было потрачено потому, что у человека кроме "знаний ассемблера" особенно ничего и не было, а потому на конкретно поставленные вопросы он не мог дать внятные ответы. Мои вопросы прежде всего касались "знаний ассемблера" (коих у меня не было) и знаний, как это работает конкретно под DOS'ом. После чего я поратил 2 часа на то, чтобы всё это повторить и запустить самому, и ещё 2 часа, чтобы научиться делать отладочную печать и в итоге выяснить причину ошибки

Просо ещё раз хотелось бы подчеркнуть - "знать ассемблер" и уметь писать на нём простенькие программы (кторые более разумно писать на языке) ещё не делает вас специалистом в этой области. И уж совершенно точно не надо рекомендовать новичкам изучать программирование с ассембелра, потому как со стороны такие предложения выглядят как чистапацанские дешовые понты

======================================== ================

Теперь вернёмся к нашему примеру hello world. Для того, чтобы сделать это более понятным, обратимся сначала к примеру из поста 83 для real-mode x86

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mov ax,3
int 10h ; перевод в текстовый режим
mov ax, 0b800h
mov es,ax
call @f
@@:
pop di
add di,msg-$+1
xor si,si
@@:
mov al,[di]
test al,al
jz exit
mov es:[si],al
inc si
inc di
inc si
jmp @b
exit:
 
ret
msg db 'Hello, world',0
В данном случае мы пишем буквы непосредственно в видеопамять. Однако писать программы на ассемблере для того, чтобы что-то напечатать на экран - занятие неблагодарное. Если мы, например, хотим что-то прочитать из файла, то непосредственно из кода программы мы этого сделать не сможем. Для этого нам нужно обратиться к операционной системе (в этом месте прошу сильно не пинать, если ошибся, т.к. DOS не знаю). В этом случае мы работаем через interrupt'ы (или как там правильно это называется) - в общем через это. Я всем этим делом владею плохо, а потому нарисую схематичный код:

Assembler
1
2
3
4
5
6
7
8
9
10
  # Печать строки
  mov ax, 9
  mov dx, msg
  int 21h
 
  # Выход
  mov ax, 0
  int 21h
 
msg: "Hello world$"
Я выбираю вариант через функции операционной системы именно потому, что для многих действий (например, для работы с файлами) придётся поступать именно так.

Далее будуть работать для кода под линукс, потому как там я хоть знаю, как всё это скомпилить за запустить. Код, аналогичный DOS'овскому, под линукс выглядит следующим образом. Вот оригинал, выдранный из поста 87

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    call @f
@@:
    pop ecx
    add ecx,msg-$+1
    mov eax,4
    mov ebx,1
    mov edx,msglen
    int 80h    <---------- печать
 
    mov eax,1 
    mov ebx,0 
    int 80h    <---------- выход
msg db 'Hello, world',0ah
msglen equ $-msg
Здесь Goodwin98 работает с псевдокомандами так, как это делают DOS'овские ассемблеры. Под линухом используются gnu'тые ассемблеры, а потому я этот код перепишу именно под него (чтобы перед глазами был пример того, как одно соотвествует другому)

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
    movl    $4, %eax
    movl    $1, %ebx
    movl    $.LC0, %ecx # значение метки (фактически адрес строки)
    movl    $.LC0f - $.LC0, %edx # разница меток
    int $0x80
 
    movl    $1, %eax
    movl    $10, %ebx
    int $0x80
.LC0:
    .string "Hello world\n"
.LC0f:
Итого, за рабочую основу возьмём этот последний код.

======================================== ================

Теперь попытаюсь объяснить, как можно сделать то же самое, но работая на Си с использованием ассемблерных вставок. Опять-таки всё это будет сделано в предположение использования компилятора gcc (в части синтаксиса ассемблерных втсавок), но при желании это переделывается под любой другой компилятор. При этом макроблоки с ассемблерными вставками формально будут находиться в отдельном файле (наподобие того, что при обычной работе библиотеки лежать где-то в стороне и мы их код не трогаем), а потому программист не заморачивается тем, что же там внутри написано, он просто использует эти макроблоки

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

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh -x
 
CC="gcc -O3 -fno-builtin -fomit-frame-pointer"
LD="ld"
 
# Эта строка для получения ассемблерного файла (чтобы глазами на него смотреть)
$CC t.c -S
 
# Эта строка для получения исполняемого файла
$CC t.c -c
$LD t.o -o a.out
strip a.out
 
# Запуск исполняемого файла
./a.out
Для начала сделаем код "в лоб". Т.е. создадим файл с непосредственными ассемблерными вставками. Файл будет выглядеть несколько коряво, но я просто хочу последовательно показать, чтобы было понятно, что откуда растёт

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
char str[] = "Hello world\n";
 
void _start (void)
{
  asm ("movl $4, %eax");
  asm ("movl $1, %ebx");
  asm ("movl $str, %ecx");
  asm ("movl $12, %edx");
  asm ("int  $0x80");
 
  asm ("movl %eax, %ebx");
  asm ("movl $1, %eax");
  asm ("int  $0x80");
}
Пока в этом месте мы делаем ровно то же самое, что если пишем ручками на ассемблере. Теперь попробуем выделаить в виде макроблока отдельно первую часть (которая занимается непосредственно печатью) и отдельно вторую часть (которая осуществляет завершение работы)

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

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/* ========== Этот код формально находится в некоем интерфейснов файле .h */
 
#define __NR_exit  1
#define __NR_write 4
 
static inline long
write (int fd, const char *buf, long count)
{
  /* Загружаем все параметры системного вызова непосредственно на нужные регистры */
  register long num asm ("%eax") = __NR_write;
  register long arg1 asm ("%ebx") = (long) fd;
  register long arg2 asm ("%ecx") = (long) buf;
  register long arg3 asm ("%edx") = (long) count;
 
  /* Результат, возвращаемый системного вызова */
  register long res asm ("%eax");
 
  /* Пишем вставку в формате gnu. Параметры num, arg1, arg2, arg3 являются
   * ВХодными аргументами вставки, а аргумент - ВЫХодным */
  asm volatile ("int $0x80"
                : "=r" (res)
                : "r" (num), "r" (arg1), "r" (arg2), "r" (arg3));
 
  return res;
}
 
static inline void
exit (int exit_code)
{
  register long num asm ("%eax") = __NR_exit;
  register long arg1 asm ("%ebx") = (long) exit_code;
 
  asm volatile ("int $0x80"
                :
                : "r" (num), "r" (arg1));
}
 
/* ========== А этот код - это уже "наша программа" */
 
void _start (void)
{
  int r;
 
  write (1, "Hello world\n", 12);
  exit (10);
}
А ассемблерный текст, соотвествующий данному коду вот такой:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    .file   "t.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "Hello world\n"
    .text
    .p2align 4,,15
.globl _start
    .type   _start, @function
_start:
    pushl   %ebx
    movl    $4, %eax
    movl    $1, %ebx
    movl    $.LC0, %ecx
    movl    $12, %edx
#APP
    int $0x80
#NO_APP
    movl    $1, %eax
    movb    $10, %bl
#APP
    int $0x80
#NO_APP
    popl    %ebx
    ret
    .size   _start, .-_start
    .ident  "GCC: (GNU) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)"
    .section    .note.GNU-stack,"",@progbits
С непривычки тут режет глаза много "лишнего" - куча всяких псевдокоманд. Дело в том, что в линуксе генерируется файл в некоем формате elf, который соотвествует формату .exe под DOS/Windows. Но не формат .com, т.к. этот формат есть только для DOS/Windows. Формат бинарного elf более сложный, а потому нужны некоторые телодвижения для сброса кода в него. Тем более, что компилятор работает в предположении, что мы пишем "честное приложене", а потому тут видится много "мусора", который на самом деле на количестве кода никак не отражается. Елинственное, что тут дейстивтельно лишнее - так это операции "pushl %ebx" в начале и "popl %ebx" и "ret" в конце. Это тоже следствие того, что с точки зрения компилятора мы строим "обычный" код, а потому он делает потуги по сохранению stack pointer'а, а так же код выхода из процедуры

А в завершение можно просто продизассемблировать полученный исполняемый файл. Правда здесь дизассемблируется только фрагмент кода. Фрагмент данных оказываются в отдельном сегменте (с точки зрения формата elf) и потому в эту выдачу не попадают. Данные печатаются отдельным приказом

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ objdump -d a.out
...
08048080 <_start>:
 8048080:   53                      push   %ebx
 8048081:   b8 04 00 00 00          mov    $0x4,%eax
 8048086:   bb 01 00 00 00          mov    $0x1,%ebx
 804808b:   b9 a2 80 04 08          mov    $0x80480a2,%ecx
 8048090:   ba 0c 00 00 00          mov    $0xc,%edx
 8048095:   cd 80                   int    $0x80
 8048097:   b8 01 00 00 00          mov    $0x1,%eax
 804809c:   b3 0a                   mov    $0xa,%bl
 804809e:   cd 80                   int    $0x80
 80480a0:   5b                      pop    %ebx
 80480a1:   c3                      ret
 
$ objdump -s -j .rodata a.out
...
Contents of section .rodata:
 80480a2 48656c6c 6f20776f 726c640a 00        Hello world..
======================================== ================

Попробуем вернуться к старому вопросу

Цитата Сообщение от Ёрик Посмотреть сообщение
Еще один момент: мы хотим сделать парсер,напр,есть какой-н. файл большой текстовый в компании,не буду фантазировать,что мы хотим найти(информацию о email-,телефонные номера и т.п.), и он весит порядка 100-300 мб
Понятно дело, что такое мне сейчас писать не хочется, но давай возьмём что-нибудь более простое, чтобы не писать длинную программу. Примеров задач по текстовой обработке файлов полно на этом форуме. Возьмём, к примеру вот такую поставновку задачи

На вход программы подаётся текстовый файл. Распечатать все строки файла таким образом, чтобы буквы в кадой строке шли в обратном порядке
Я хочу продемонстрировать лишь принцип работы. Поэтому предлагаю сделать некие ограничения, чтобы не замусоривать программу дополнительнфми кодами:
  • Считаем, что тесктовый файл присуствует и доступен для чтения - чтобы не делать дополнительных проверок на это
  • Полагаем, что файл завершается символом перевода строки, чтобы исклчить дополнительную проверку
  • Считаем, что размер файла ограничен (например, не более 4 килобайт), чтобы не равзодить в программе дополнительного геморроя

В любом случае при снятии этих ограничений придётся писать дополнительный код хоть на ассемблере, хоть на языке, поэтому для демонстрации считаю эти ограничения допустимыми

При вставлении кода на форум я намеренно "спрятал" внутренности файла "syscall.h", потому как мы считаем, что она уже кем-то написана, а мы её только используем. Точно так же, как этот кто-то реализовал нам системные библиотеки, а мы их используем при написании программы на языке. Ну и по поводу этого же syscall.h. Можешь заметить, что реализации процедур, осуществляющих системные вызовы, очень похожи друг на друга, с небольшими лишь отличиями. Именно поэтому в 81-м посте они были реализованы через макросы. Но такой вариант тебе пока малопонятен, а потому оставлю в виде кода

syscall.h

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* Для подцепления значений флагов для open. И, поскольку мы подцепили систсемный
 * инклюд, то переобзовём "наши" процедуры, чтобы не конфликтовать по именам
 * с описаниями стандартных библиотечных */
#include <sys/fcntl.h>
 
#define __NR_exit  1
#define __NR_read  3
#define __NR_write 4
#define __NR_open  5
 
static inline long
my_write (int fd, const char *buf, long count)
{
  /* Загружаем все параметры системного вызова непосредственно на нужные регистры */
  register long num asm ("%eax") = __NR_write;
  register long arg1 asm ("%ebx") = (long) fd;
  register long arg2 asm ("%ecx") = (long) buf;
  register long arg3 asm ("%edx") = (long) count;
 
  /* Результат, возвращаемый системного вызова */
  register long res asm ("%eax");
 
  /* Пишем вставку в формате gnu. Параметры num, arg1, arg2, arg3 являются
   * ВХодными аргументами вставки, а аргумент - ВЫХодным */
  asm volatile ("int $0x80"
                : "=r" (res)
                : "r" (num), "r" (arg1), "r" (arg2), "r" (arg3));
 
  return res;
}
 
static inline long
my_read (int fd, char *buf, long count)
{
  register long num asm ("%eax") = __NR_read;
  register long arg1 asm ("%ebx") = (long) fd;
  register long arg2 asm ("%ecx") = (long) buf;
  register long arg3 asm ("%edx") = (long) count;
 
  register long res asm ("%eax");
 
  asm volatile ("int $0x80"
                : "=r" (res)
                : "r" (num), "r" (arg1), "r" (arg2), "r" (arg3));
 
  return res;
}
 
static inline long
my_open (const char *path, int flags)
{
  register long num asm ("%eax") = __NR_open;
  register long arg1 asm ("%ebx") = (long) path;
  register long arg2 asm ("%ecx") = (long) flags;
 
  register long res asm ("%eax");
 
  asm volatile ("int $0x80"
                : "=r" (res)
                : "r" (num), "r" (arg1), "r" (arg2));
 
  return res;
}
 
static inline void
my_exit (int exit_code)
{
  register long num asm ("%eax") = __NR_exit;
  register long arg1 asm ("%ebx") = (long) exit_code;
 
  asm volatile ("int $0x80"
                :
                : "r" (num), "r" (arg1));
}


C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "syscall.h"
 
static char buff_r[4096], buff_w[4096];
 
void _start (void)
{
  int fd;
  char *p1, *p2, *p3, *p4;
 
  /* Открываем файл */
  fd = my_open ("a.txt", O_RDONLY);
 
  /* Читаем файл в буффер в рамках наших ограничений. В условиях без ограничений
   * надо проверять результат, возвращаемый процедурой, чтобы понять, сколько
   * байт считано. И читать в цикле до тех пор, пока процедура не вернёт 0.
   * В условиях без ограничений может оказаться так, что длина строки составляет
   * 100 гигабайт (т.е. больше, чем мы вообще имеем памяти). Понятное дело,
   * что такие случаи нормально не разрулишь ни на ассемблере, ни на языке. */
  my_read (fd, buff_r, sizeof (buff_r));
 
  p2 = buff_r;
  while (*p2 != 0)
    {
      /* Ищем символ перевода строки. По окончании поиска p2 установится на позицию,
       * следующую за символом перевода строки.
       * p1 соотвествует началу найденной строки, p2 - концу */
      p1 = p2;
      while ( *(p2++) != '\n' );
 
      /* Делаем реверсное копирование, при этом знак перевода строки
       * должен быть всегда в конце (т.е. в копировании он не участвут,
       * а потом дорисовывается ручками).
       * p3 - src, p4 - dst */
      p3 = p2 - 2;
      p4 = buff_w;
      while (p3 != (p1-1))
        *p4++ = *p3--;
      *p4 = '\n';
 
      /* Печать инверсной строки */
      my_write (1, buff_w, p4 - buff_w + 1);
    }
 
  my_exit (10);
}
И вот итоговый ассемблерный код. Я удалил из него псевдокоманды, чтобы не резали глаза и написал некоторые комментарии

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
    # Вызов my_open. "Лишними" операциями являются операции сохранения
    # в стеке регистров. Это всё следствие того, что компилятор думает,
    # что мы пишем "честную программу". Эти операции являются одноразовыми,
    # т.е. будут только в начале и в конце нашей программы и на
    # общую производительность практически не оказывают влияния
    pushl   %ebp
    movl    $5, %eax
    pushl   %edi
    xorl    %ecx, %ecx
    pushl   %esi
    pushl   %ebx
    movl    $.LC0, %ebx
    subl    $4, %esp
    int $0x80
 
    # --------------------
 
    # Вызов my_read
    movl    $buff_r, %ecx
    movl    %eax, %ebx
    movl    $4096, %edx
    movl    $3, %eax
    int $0x80
 
    # --------------------
 
    cmpb    $0, buff_r
    je  .L2
    movzbl  buff_r, %eax
    movl    $1, %ebp
    movl    %ecx, %esi
    movl    %ebp, %edx
    subl    $buff_w, %edx
    movl    %edx, (%esp)
    jmp .L17
 
    # --------------------
 
    # Цикл поиска знаков переноса строки (29-я строка исходника).
    # Видим, что цикл сделан быстро и не содержит мусора, а это главное,
    # т.к. в первую очередь важен быстрый код в "горячих" участках программы,
    # которые работают чаще других. Смысл конструкции ".p2align 4,,7" в том,
    # что операция "movzbl" должна находиться на выравненной позиции в коде,
    # чтобы работать быстрее - это особенность процессора, знание
    # которой мы переложили на компилятор
    .p2align 4,,7
.L19:
    movzbl  (%esi), %eax
.L17:
    addl    $1, %esi
    cmpb    $10, %al
    jne .L19
 
    # --------------------
 
    leal    -2(%esi), %edx
    movl    $buff_w, %edi
    leal    -1(%ecx), %eax
    cmpl    %eax, %edx
    je  .L9
    movl    %esi, %edx
    addl    $1, %ecx
 
    # --------------------
 
    # Цикл реверсного копирования (строки 37-38 исходника). Здесь также
    # видим, что "горячий" участок построился без мусора
    .p2align 4,,7
.L10:
    movzbl  -2(%edx), %eax
    subl    $1, %edx
    movb    %al, (%edi)
    addl    $1, %edi
    cmpl    %ecx, %edx
    jne .L10
 
    # --------------------
 
.L9:
    movl    (%esp), %edx
 
    # Вызов my_write, к которому подмешался код записи последнего знака
    # переноса строки (39 строка). Тоже своеобразный учёт правила планирования
    # (чтобы код лучше параллелился на исполняющие устройства)
    movl    $4, %eax
    movl    %ebp, %ebx
    movb    $10, (%edi)
    movl    $buff_w, %ecx
    addl    %edi, %edx
    int $0x80
 
    # --------------------
 
    movzbl  (%esi), %eax
    testb   %al, %al
    je  .L2
    movl    %esi, %ecx
    jmp .L17
.L2:
 
    # --------------------
 
    # Вызов my_exit
    movl    $1, %eax
    movl    $10, %ebx
    int $0x80
 
    # --------------------
 
    # Восстановление регистров, которые компилятор сохранил в начале процедуры
    # (причина описана в коментарии в начале процедуры)
    addl    $4, %esp
    popl    %ebx
    popl    %esi
    popl    %edi
    popl    %ebp
    ret
У меня исполняемый файл получился размером 668 байт

======================================== ================

Какие плюсы при написании на Си:
  • Код удобнее читать и развивать.
  • Тратится меньше времени на разработку, отладку, поддержание, развитие
  • Код можно оформлять в виде процедур. Такой код удобнее смотреть глазами, но при этом компилятор его про'inline'ит, а потому процедурных вызовов как таковых в коде не будет
  • Проще делать код "под процессор". На разных версиях процессора отличаются правила планирования операций (т.е. порядок, в котором операции присуствуют в коде) - это некое очень аппаратное свойство процессора. Неправильно выбранный порядок может дать замедление кода, а потому при ручном программировании довольно тяжело постоянно выдерживать все правила планирования. Компилятор всё это сделает автоматически
  • За счёт использования дополнительных средств условной компиляции в программу легко встраивается отладочная печать, код которой встраивается или выбрасывается одним взмахом левой руки

Минусы при написании на Си:
  • Временами лезет непонятный мусорный код, природу которого можно понять, только понимая принципы работы компилятора
  • В каких-то случаях не удаётся от компилятора добиться предельной производительности на критическом участке и код приходится оформлять в виде ассемблерной вставки, которую, тем не менее, проще поддерживать, чем полностью написанный на ассемблере код, т.к. распределение регистров внутри вставки можно переложить на компилатор
  • Не все вещи можно аккуратно сделать через компилятор. Например, какие-то штуки, работающие в обход программных соглашений архитектуры. Например, в коде операционных систем вызов пользовательского обработчика сигналов сделан путём ручной модификации процедурного стека вызовов, чего компилятор в каких-то случаях может не пережить, а потому такой код лучше писать ни чистом ассемблере (именно тот фрагмент, где происходит модификация стека, передача управления на обработчик сигнала и отработка возврата из обработчика

======================================== ================

Вернёмся ещё раз к тому же вопросу

Цитата Сообщение от Ёрик Посмотреть сообщение
Еще один момент: мы хотим сделать парсер,напр,есть какой-н. файл большой текстовый в компании,не буду фантазировать,что мы хотим найти(информацию о email-,телефонные номера и т.п.), и он весит порядка 100-300 мб, и если ты потратишь 15 сек на написание программы на С,программма будет выполняться довольно долго,а на ассемблере мало того,что com файл будет весить меньше 500 байт,так еще и выполняться быстре,чем программа,код которой написан на Perl. Evg,понимаю ,что разговарию с профи,поэтому не хочу долго спорить. На этом дискуссию хотелось бы закончить.
Вся работа с файлами делается через операционную систему. А поскольку файл это "медленное" (с точки зрения процессора) внешнее устройство, то получается так, что основное время работы программы будет занимать торчание в операционной системе в момент чтения данных из файла. В этом отношении код на чистом ассемблере и на Си будет исполняться практически одно и то же количество времени. Код на Perl - навскидку медленее не более, чем в два раза (но совершенно точно не в 10 раз) - это кажется, что интерпретация работае медленно, но на самом деле львиную долю времени работы в момент интерпретации занимают непосредственно коды на Си, которые исполняют Perl'овские макрооперации. Если при такой поставноке задачи делать выбор между ассемблером, Си и Perl'ом - я однозначно выберу Perl

Хочется ещё раз подчеркунть, что не надо зацикливаться на чём-то одном. Оптимальны вариант почти всегда заключается в разумной комбинации использования разных технологий и диктуется в первую очередь надёжностью и затрачиваемым временем на поддержку и развития программы, а не реальным временем её исполнеия. Понятно, что если один вариан в 5 раз геморройнее, но в 50 раз быстрее - надо брать геморройный вариант. Но если вариант на ассемблере работает в 2 раза быстрее, но требует в 10 раз больше времени на надёжную отладку, то такой вариант однозначно идёт лесом

Добавлено через 11 минут 13 секунд
Всю эту технологию можно повторять и под DOS и под Winddows. Только надо понять, как там ручками правильно запустить компилятор и как правильно поддержать ассемблерные вставки в файле syscall.h. Код программы при этом не меняется
14
4 / 3 / 0
Регистрация: 03.05.2009
Сообщений: 82
20.07.2009, 23:15  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Автор давно уже тему не читает. Просто так получилось, что эта тема вылилась в дальнейшие обсуждения работы ассемблере



Именно это я и пытаюсь объяснить людям, считающим, что "выучили ассемблер". Но не могу подобрать внятные слова

Автору всё интересно она следит за Вашей дискуссией очень долго. Но жаль что откланились от заданных параметров для чайников и прониклись глубже. Я хотела что бы чайники войдя в эту тему обрели для себя начальные знания по асму как и я. Если можно давайте возвратимся к начальному этапу по асму а глубокое изучение будет через создание новых тем. Вед тема может вдохновить будуших профи...


Вот что я для себя уяснила за прошедшее время отсутстствия на дискуссиях. По асму оказалось у меня куча книг пока не очень понятных и самая главная понятная книга для начинаюших это - Калашников "Ассемблер это просто" Скачайте эту книгу, установите себе на флешку Windows9x и все калашниковские проги будут там работать.

Я хочу задать вопрос профайлам: объясните пожалуйста где можно найти таблицу цфровых значений команд асма например:
mov - hex,b значения
xor ...
ret ...
push ... может я что то пропустила?

Добавлено через 10 минут 14 секунд
Цитата Сообщение от Anthony Посмотреть сообщение
Sayfera русскому языку для начала научись.

Если Вы считаете себя профи русского языка то Вам здесь не место, тут обсуждаются вопросы по программированию на ассемблере!
0
Эксперт JavaЭксперт С++
 Аватар для M128K145
8384 / 3618 / 419
Регистрация: 03.07.2009
Сообщений: 10,709
20.07.2009, 23:30
Цитата Сообщение от Evg Посмотреть сообщение
И уж совершенно точно не надо рекомендовать новичкам изучать программирование с ассембелра, потому как со стороны такие предложения выглядят как чистапацанские дешовые понты
Evg, вот не могу согласиться. Честно признаюсь, что я "знаю ассемблер", но тем не менее, мне кажется, что начинать изучать лучше с асма. Он позволяет немного конкретизировать мышление. Лично у меня после начала изучения ассемблера, существенно улучшилось понимание тех же плюсов, если можно так сказать, то алгоритмическое понимание происходящего
0
45 / 45 / 1
Регистрация: 23.05.2009
Сообщений: 92
01.08.2009, 01:33
Цитата Сообщение от M128K145 Посмотреть сообщение
Evg, вот не могу согласиться. Честно признаюсь, что я "знаю ассемблер", но тем не менее, мне кажется, что начинать изучать лучше с асма. Он позволяет немного конкретизировать мышление. Лично у меня после начала изучения ассемблера, существенно улучшилось понимание тех же плюсов, если можно так сказать, то алгоритмическое понимание происходящего
А вот мне интересно стоит ли вообще сейчас оптимизировативать программа с небольшим программным кодом, так как на современных компьютерах эта проблема практически отпала из-за больших вычислительных мощностей.
1
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
01.08.2009, 01:41
А вот из-за подобных мыслей у разработчиков, и тормозят элементарнейшие программы у пользователей, которые не хотят кормить топ менеджеров IT компаний.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
03.08.2009, 21:06
Цитата Сообщение от Goodwin98 Посмотреть сообщение
А вот из-за подобных мыслей у разработчиков, и тормозят элементарнейшие программы у пользователей, которые не хотят кормить топ менеджеров IT компаний.
Видишь ли, если разработать мегабыструю программу, но потратить на разработку 10 лет, то в современном мире это мало кому будет нужно. А потому разработчики и спешат, чтобы выйти на рынок раньше конкурентов. С другой стороны не у всех всё очень хреново. Гугл был последним среди разработчиков браузера, но тем не менее по скороксти работы, чувствую, остальные браузеры ещё не скоро догонят хром
0
MCSD: APP BUILDER
 Аватар для IT_Exp
8795 / 1074 / 104
Регистрация: 17.06.2006
Сообщений: 32,602
03.08.2009, 21:11
Goodwin98,
А вот из-за подобных мыслей у разработчиков, и тормозят элементарнейшие программы у пользователей, которые не хотят кормить топ менеджеров IT компаний.
Я открою тебе одну простую истину: ВРЕМЯ ПРОГРАММИСТОВ СТОИТ ДОРОЖЕ ЧЕМ КУПИТЬ МОЩНОЕ ЖЕЛЕЗО. И сейлсы это очень хорошо понимают.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
09.08.2009, 11:58
На мой взгляд одного только отсутствия undo достаточно для того, чтобы такой редактор выкинуть в печь. Есть много редакторов, которые позволяют настраивать цветовую подсветку, и под винду они наверное тоже есть
0
Эксперт JavaЭксперт С++
 Аватар для M128K145
8384 / 3618 / 419
Регистрация: 03.07.2009
Сообщений: 10,709
09.08.2009, 12:20
Rififi, другое дело что софт они пишут для пользователей и не у всех железо может потянуть. Из-за чего многие пользователи отказываются от этого софта в пользу конкурента, с похожим ПО, но меньшими требованиями
0
 Аватар для svchost6
0 / 0 / 0
Регистрация: 07.08.2009
Сообщений: 8
09.08.2009, 17:00
А Sayfera - это реальный персонаж или чейто виртуал)?(колитесь блин)
Это ведь шутка)?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
09.08.2009, 17:00

Хочу научится писать парсеры. С чего начать?
Хочу освоить написание парсеров. Посоветуйте какие функции стоит изучить! Также буду благодарен, если подскажите где почитать про...

Хочу научится программировать но не знаю с чего начать
Всем привет! Меня зовут Александр. Хочу научиться программировать на языке . Опыта в этой сфере нету, но есть желание подскажите с чего...

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

Помогите научится!!!!
Здравствуйте добрые люди, я начал заниматься ремонтом стиральных машинок, но проблема в том, что модули(микросхемы), я сам не могу...

Как научится ООПэшить?
Как научится &quot;ООПэшить&quot;? Я самоучка, &quot;фрилансю&quot; на пхп и яваскрипте уже пару лет, но когда я пытаюсь написать что-нибудь на ООП (если можно...


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

Или воспользуйтесь поиском по форуму:
113
Закрытая тема Создать тему
Новые блоги и статьи
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы ## О чём эта статья В процессе построения ОДУ-модели (система дифференциальных. . .
сукцессия 24. Промежуточное общее описание модели
anaschu 12.07.2026
Хендофф: модель АМ→ЭКМ сукцессии микоризы (ризосфера, 50 лет) Содержание проекта Симуляция вековой (50 лет) экологической сукцессии в почве леса Основные участники: АМ-гриб, ЭКМ-гриб,. . .
сукцессия 23. Более физиологичная физиология, более экологичная экология, более диффурные диффуры.
anaschu 12.07.2026
Что реально нашли и починили за эти 5 часов Правило Линдемана (КПД конверсии сахара в тело, kEff) — раньше 100% полученного углерода шло прямо в биомассу гриба; теперь только kEff=0. 5 (после. . .
сукцессия 22. От артефактов к физиологии: калибровка агентной модели грибной сукцессии для воспроизведения сезонной динамики и pH-плато
anaschu 11.07.2026
Аннотация В данной работе представлена калибровка агентной модели динамики грибных сообществ (fungal-succession), направленная на устранение нефизичных артефактов (коллапс биомассы, мгновенное. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru