Форум программистов, компьютерный форум, киберфорум
Наши страницы

Assembler для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Appostl
15 / 4 / 0
Регистрация: 30.12.2009
Сообщений: 93
#1

Написать программу, выводящую строку "Hello World" на экран - Assembler

20.10.2011, 12:51. Просмотров 53272. Ответов 39
Метки нет (Все метки)

Написать прогармму выводящую строку "Hello World" на экран

Заранее спасибо
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.10.2011, 12:51
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Написать программу, выводящую строку "Hello World" на экран (Assembler):

Написать программу на ассемблере, выводящую на экран строку 100 раз - Assembler
Написать программу на ассемблере, выводящую на экран строку 100 раз.

Составьте программу, выводящую на экран 5 строк «Hello, World!» - Assembler
Всем доброго времени суток! Есть задание: 1.Составьте программу, выводящую на экран 5 строк «Hello, World!», используя циклические...

Составить программу для вывода на экран дисплея "бегущей" строки "Периферийные устройства ЭВМ" из (12,40) в (12,10) - Assembler
Нужно написать две программы вот их условия: 1.Составить программу для вывода на экран дисплея "бегущей" строки "Периферийные...

Необходимо строку тип ""str1" "str2"",0 преобразовать в строку типа - Assembler
Необходимо строку тип ""str1" "str2"",0 преобразовать в строку типа "str2",0 label_parse_string: inc EAX cmp EAX, ' ' jnz...

Написать программу, выводящую на экран флаг Бангладеша - Assembler
Здравствуйте ! Необходимо написать программу на Ассемблере, выводящую на экран флаг Бангладеша. Флаг изображается в виде квадрата,...

Написать программу выводящую на линейку семисегментных индикаторов АЛС 318 бегущую строку - Assembler
Помогите с программой: Написать программу выводящую на линейку симесигментных индикаторов АЛС 318 бегущую строку слова "ПРОБА"....

39
vital792
1995 / 1267 / 56
Регистрация: 05.06.2010
Сообщений: 2,213
12.03.2012, 14:32 #16
Цитата Сообщение от Typoii Посмотреть сообщение
самая лучшая реализация
ага - макросом, так любой код в одну строку можно уместить)
0
Charles Kludge
Клюг
7637 / 3152 / 364
Регистрация: 03.05.2011
Сообщений: 8,382
14.03.2012, 22:46 #17
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Графика, толсто.[FASM]
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
    format MZ
    heap    0
    stack   100h
    entry   main:start
segment main    use16
start:  push    0                   
    pop fs                      ; vector table
    mov ax,data_segment
    mov ds,ax
    mov es,ax
    mov ax, 13h            ; modeX Graphics 320x200x256, 40x25, 8x8     
    int 10h
    mov eax, dword [fs:43h*4]
    mov dword [int43], eax     ; Get 8x8 chargen ptr
    mov si, hello
next:   call    gotoxy
    lodsb
    or  al,al
    jz  exit
    cmp al,20h  ; <space>?
    jnz @1
    add byte [Y], 11
    mov byte [X], 0
    jmp next
@1: movzx   ax,al
    shl ax, 3   ; ax*8
    push    si
    push    ds
    lds si, [int43]
    add si, ax
; Вывод на экран 
    mov cx, 8 
loo0:   lodsb
    mov bl, al
    push    cx
    mov cx, 8
loo1:   mov al, 20h
    rcl bl, 1
    jnc @@1
    mov al, 0DBh
@@1:    int 29h
    loop    loo1
    pop cx
    inc byte [es:Y]
    call    gotoxy
    loop    loo0
    pop ds
    pop si
    add byte [X], 8
    sub byte [Y], 8
    jmp next    
; выход
exit:   xor ah, ah
    int 16h
    mov ax, 03h
    int 10h
    mov ah, 4Ch
    int 21h
gotoxy: pusha
    mov ah,2
    xor bx,bx
    mov dx, word [es:XY]
    int 10h
    popa
    ret
segment data_segment use16 
int43:  dd  ?
XY:
X:  db  0
Y:  db  3
hello:  db  'Hello world',0
0
Charles Kludge
Клюг
7637 / 3152 / 364
Регистрация: 03.05.2011
Сообщений: 8,382
10.04.2012, 19:55 #18
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Ну и ещё изврат - шлём сообщение самому себе через LAN Manager[FASM]:
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
        org 100h
        push    cs
        pop ax
        mov [rcpt_seg], ax
        mov [msg_seg], ax
        mov ax, 5E00h   ; DOS 3.1+ network
        mov dx, wkst_nm ; получить
        int 21h             ; имя локальной машины
        mov ax, 5F40h       ; LAN Manager Enhanced DOS
        mov dx, LM_MSG  ; отправить сообщение
        int 21h             ; самому себе
        int 20h
; LAN Manager NetMessageBufferSend parameter structure:
LM_MSG:                                 ;
; DWORD -> имя адресата (name for specific user, name* for domain wide name, * for broadcast)
rcpt_ofs:   dw  wkst_nm
rcpt_seg:   dw  ?
; DWORD -> текст сообщения
msg_ofs:    dw  msg
msg_seg:    dw  ?
msg_sz:     dw  msg_len     ; длина соощения
;
wkst_nm:    db  10h dup(?)  ; имя раб. станци
msg     db  'Hello, World!'
msg_len     =   $ - msg
2
HITMAN
Absolution
155 / 125 / 3
Регистрация: 22.06.2011
Сообщений: 1,779
11.04.2012, 06:45 #19
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Для DZENствующих!
Компилить этим зверем.
w 'MZ'
j 3c 0c
j 0c 'PE' 0 0
w 4c01; Тип процессора
w 0100; Число секций
a c e000; Размер дополнительного заголовка
w 0f01; Тип файла
w 0b01; "Магическое" значение
a e d4100000; Ссмещение точки входа
a 8 00004000; Начальный адрес загрузки (4 байта) *****
w 00100000; Выравнивание секций (4 байта)
w 00020000; Выравнивание в файле (4 байта)
w 0400; Старшая версия Windows (2 байта)
a 6 0400 ;Старшая версия подсистемы
a 6 00200000; Размер загруженного файла
w 30010000; Размер всех заголовков в файле (4 байта)
a 4 0200; Подсистема: 02 - графическая, 03 - консольная
a 2 00001000; Зарезервированный размер стека (4 байта)
w 00100000; Выделенный размер стека (4 байта)
w 00001000; Зарезервированный размер кучи (4 байта)
w 00100000; Выделенный размер кучи (4 байта)
a 4 10000000; Число элементов каталога смещений (4 байта)
a 8 56100000; смещение таблицы импорта (4 байта)
w 3c000000; размер таблицы импорта (4 байта)
; Начало таблицы секций
a 78;Первая секция импорта
w 00100000; размер секции в памяти
w 00100000; смещение секции относительно адреса загрузки
w 00020000; размер данных секции в файле
w 00020000; смещение начала данных секции в файле
a 0c 400000c0; атрибуты первой секции
; Секция 1 *************************************************
s 0200

l user32 'User32.dll' 0 0
l _user32 0 0'MessageBoxA'0

l kernel32 'Kernel32.dll' 0 0; имя 2 модуля
l _kernel32 0 0'ExitProcess'0
;w 0 0'LoadLibraryA'0

l __user32 ^_user32 0 0 00000000; таблица поиска 1
l __kernel32 ^_kernel32 0 0 00000000; таблица поиска 2

; 1 IAT
l MessageBox
w ^_user32 0000;Смещение таблицы поиска
w 00000000

; 2 IAT
l ExitProcess
w ^__kernel32 0000
;l LoadLibrary 00000000
w 00000000

; таблица импорта:
; 1 модуль
w ^__user32 0000; указатель на 1 таблицу поиска
a 8; 2 пустых поля
w ^user32 0 0; указатель на имя 1 модуля
w ^MessageBox 0000; указатель на 1 IAT

; 2 модуль
w ^__kernel32 0000; указатель на 2 таблицу поиска
a 8; 2 пустых
w ^kernel32 0 0; указатель на имя 2 модуля
w ^ExitProcess 0000; указатель на 2 IAT
j a0
; последняя запись - все нули
l caption 'translator'20'version'20'1.0'0
l text 'Hi! I' 27 'm the' ' example' ' program!'0
; помещаем в стек параметры MessageBoxA
w 6a00
w 68 @caption
w 68 @text
w 6a00
; вызываем MessageBoxA
w ff15 @MessageBox
; помещаем в стек параметр (0)
w 6a00
; вызываем ExitProcess
w ff15 @ExitProcess
1
Mikl___
Заблокирован
Автор FAQ
11.04.2012, 07:14 #20
IOAN, так придется показывать, как создать MessageBox на разных диалектах ассемблера, а их штук двадцать наберется. Лучше по MessageBox создать отдельную тему и я мог бы показать, как только на MASM создать MessageBox 10 способами
0
Charles Kludge
Клюг
7637 / 3152 / 364
Регистрация: 03.05.2011
Сообщений: 8,382
11.04.2012, 10:30 #21
Mikl___, можно и через undoc BOP_3RDPARTY - MessageBox() из доси вывести.
И да, топик-таки лучше прилепить.
0
HITMAN
Absolution
155 / 125 / 3
Регистрация: 22.06.2011
Сообщений: 1,779
11.04.2012, 11:55 #22
Mikl___, тему создать это легко, а почему эту не продолжить?
1
Mikl___
11.04.2012, 13:05
  #23

Не по теме:

чтобы тема не выродилась, a о MessageBox'e создавай новую тему

0
HITMAN
Absolution
155 / 125 / 3
Регистрация: 22.06.2011
Сообщений: 1,779
11.04.2012, 13:10 #24
Mikl___,

Не по теме:

понято!

1
Lizakotenkova
0 / 0 / 1
Регистрация: 04.05.2011
Сообщений: 57
02.12.2012, 06:17 #25
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
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
;TASM, COM - файл
;tasm.exe /m
;tlink.exe /t /x
;
.model tiny
.code
.386
ORG 100h
START:
    lea dx,privet
    mov ah,9
    int 21h
 
    lea dx,privet1
    int 21h
    
    mov ah,0
    int 16h
 
    ret
 
;
privet  db  13,10,'Привет!$'
privet1 db  13,10,'ЏаЁўҐв!$'
 
    end start
Можешь прокаментировать)
0
Charles Kludge
Клюг
7637 / 3152 / 364
Регистрация: 03.05.2011
Сообщений: 8,382
07.12.2013, 08:53 #26
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Продолжим извраты - теперь и под FreeBSD. include-файлы лежат на https://github.com/graudeejs/asm4BSD/tree/master/FreeBSD/include ,
в файле macros.fasm стр. 21 должна выглядеть так:
Код
        lea        esp,[esp+4*margc]    ; clear stack
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
;fasm helbsd
;ld -s -o helbsd helbsd.o
include 'BSD/macros.inc'
include 'BSD/syscall.inc'
STDOUT  = 1
format ELF
 
section '.text' executable
public _start
_start:
    syscall SYS_WRITE,STDOUT, msg, msg_size
    syscall SYS_EXIT, 0
 
section '.data' writeable
msg db 'Hello, FreeBSD world!',0xA
msg_size = $-msg
1
Jallot
2 / 2 / 0
Регистрация: 12.06.2014
Сообщений: 10
14.06.2014, 15:02 #27
Цитата Сообщение от Mikl___ Посмотреть сообщение
прямой вывод строки в видео память, выводит красные символы на черном фоне
Mikl___, там не обязательно подсчитывать длину строки, можно просто прекращать вывод символов при встрече контрольного символа в конце строки (например $)
Assembler
1
2
3
4
5
6
7
...
lodsb
cmp al, '$'
jz exit
mov ah, 07 ;белые буквы на черном фоне
stosw
...
Добавлено через 5 минут
Lizakotenkova, не обязательно пользоваться оператором lea, можно просто использовать директиву offset, (mov dx, offset privet), таким образом мы экономим байты
1
Charles Kludge
Клюг
7637 / 3152 / 364
Регистрация: 03.05.2011
Сообщений: 8,382
14.06.2014, 16:50 #28
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Продолжаем мучить фряшу — теперь вызываем системную библиотеку libc.so:
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
; fasm example of using the C library in Unix systems
; compile the source with commands like:
;   fasm libcdemo.asm libcdemo.o
;   gcc libcdemo.o -o libcdemo
;   strip libcdemo
format ELF
 
include 'ccall.inc'
 
struc tm
{
.tm_sec:    rb  2 ;  seconds after the minute -- [0,61]
.tm_min:    rb  2 ;  minutes after the hour   -- [0,59]
.tm_hour:   rb  2 ;  hours after midnight     -- [0,23]
.tm_mday:   rb  2 ;  day of the month         -- [1,31]
.tm_mon:    rb  2 ;  months since January     -- [0,11]
.tm_year:   rb  2 ;  years since 1900
.tm_wday:   rb  2 ;  days since Sunday        -- [0,6]
.tm_yday:   rb  2 ;  days since January 1     -- [0,365]
.tm_isdst:  rb  2 ;  Daylight Savings Time flag
tm_size =   $ - .
}
 
section '.text' executable
 
 public main
 extrn printf
 extrn time
 extrn strftime
 extrn localtime
 
 main:
    ccall   time, 0     ; получить время в сек. от 00:00:00 1-jan-1970
    mov [now],eax
    ccall   localtime, now  ; преобразрвать в структуру tm и получить указатель
    mov [ptime], eax
; преобразовать дату/время в строку ДД-месяц-ГГГГ ЧЧ:ММ:СС день_недели
    ccall   strftime, buf, BUFF_SZ, fmt, [ptime]
    ccall   printf, msg, buf; вывод на экран
    ret
 
section '.data' writeable
BUFF_SZ =   35
now:    dd  0
ptime   dd  ?
fmt db  '%d-%B-%Y %T, %A',0
msg db  "Hello, FreeBSD world!",0xA, 0xD,"Now %s.",0xA,0
buf rb  BUFF_SZ
0
AlexVRud
465 / 176 / 46
Регистрация: 04.07.2014
Сообщений: 482
16.09.2014, 14:06 #29
Что-то совсем мало сказано про использование стандартной библиотеки Си.

Этот пост я направляю в первую очередь преподавателям и учителям.

Начинать HelloWorld с реализации для DOS, с использованием WinAPI или макросов, по моему мнению, очень не правильно.
Если изучать Ассемблер после Си, то можно легче понять происходящее, а самое главное, объяснить всем студентам/школьникам значимость Ассемблера, архитектуру компьютера и правила исполнения программ. Современный курс не должен концентрироваться на 100500 способах вывода последовательности байт в консоль и изучении систем исчисления. Чем быстрее будет изучен математический сопроцессор, SSE и прочие вкусности, тем больше можно успеть в рамках курса. А это значит, что надо пользоваться готовыми инструментами для взаимодействия человека и компьютера.

Win32

Теперь вспомним, что в Си программа начинает исполняться с функции main. Реализуем её. Эта функция возвращает число с типом int, для Win32, в соответствии с "соглашением о вызове" cdecl, оно должно быть возвращено через регистр EAX.
Процесс сборки готовой программы разобьём на два этапа:
- компиляция asm-файла в объектный файл,
- компоновка объектного файла со стандартными библиотеками средством, предполагающим сборку Си-приложения.
Первый пункт требует, что бы мы не забыли "опубликовать" нашу функцию. Второй - предполагает, что компоновщик будет ждать функцию main.
В качестве компилятора языка Ассемблера я буду использовать NASM, поменять его на другой не составит труда. В роли компоновщика рассмотрю MinGW и MSVS.

Первый пример: "Ничего не делаем"
Assembler
1
2
3
4
5
6
global _main
 
section .code
_main:
        mov     eax, 13
        ret
Компилируем, компонуем (MinGW), запускаем и смотрим код ошибки
Bash
1
2
3
4
5
6
7
8
D:\work>nasm -f win32 hello.asm -o hello.obj
 
D:\work>mingw32-gcc hello.obj -o hello.exe
 
D:\work>hello.exe
 
D:\work>echo %ERRORLEVEL%
13
Добавим использование функции printf. Не забываем объявить о ней компилятору Ассемблера:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
global _main
extern _printf
 
section .code
_main:
        push    msg
        call    _printf
        add     esp, 4
 
        mov     eax, 0
        ret
 
section .data
msg     db "Hello World", 10, 0
Компилируем, компонуем, запускаем и видим долгожданную строку.
Я говорил, что можно скомпоновать и с помощью MSVS:
Bash
1
D:\work>link hello.obj /out:hello.exe /subsystem:console /defaultlib:msvcrt
Теперь вспомним, что в main передаются ещё и параметры. Они лежат в стеке. Там сейчас:
- адрес возврата (4 байта),
- int argc (4 байта),
- char *argv[] (4 байта).
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
global _main
extern _printf
 
section .code
_main:
        mov     eax, [esp+8]
        mov     eax, [eax]
        push    eax
        push    msg
        call    _printf
        add     esp, 8 ; Не забываем, что теперь надо убрать 8 байт из стека
 
        mov     eax, 0
        ret
 
section .data
msg     db "Hello World!!!", 10
        db "My name is '%s'", 10, 0
Linux (x86)

А тут ничего почти не изменилось . Мы не использовали системнозависимых функций. Но нам потребуется:
- избавиться от префикса "_",
- изменить формат объектного файла
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
global main
extern printf
 
section .code
main:
        mov     eax, [esp+8]
        mov     eax, [eax]
        push    eax
        push    msg
        call    printf
        add     esp, 8
 
        mov     eax, 0
        ret
 
section .data
msg     db "Hello World!!!", 10
        db "My name is '%s'", 10, 0
Компилируем, компонуем, запускаем:
Bash
1
2
3
4
5
~/work$ nasm -f elf32 hello.asm -o hello.o
~/work$ gcc hello.o -o hello
~/work$ ./hello
Hello World!!!
My name is './hello'
Замечание: Если добавить ключ "--prefix _" в nasm при компиляции в Win32, то последний код, будет работоспособным.

Win64

Тут нас ждут следующие изменения:
- Регистры увеличились и в размера и в количестве .
- Параметры передаются через регистры, для нас важно, что целые числа и указатели будут лежать в RCX, RDX, R8 и R9, действительные в XMM0L, XMM1L, XMM2L и XMM3L, остальное через стек.
- Вызывающая подпрограмма должна зарезервировать в стеке место для 4-х регистров!!!
- Префикс не нужен.
- Изменился формат объектных файлов.
Остальное читаем в http://msdn.microsoft.com/en-us/library/ms235286.aspx

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
global main
extern printf
 
section .code
main:
        sub     rsp, 4*8
 
        mov     rdx, [rdx]
        mov     rcx, msg
        call    printf
 
        add     rsp, 4*8
        mov     rax, 0
        ret
 
section .data
msg     db "Hello World!!!", 10
        db "My name is '%s'", 10, 0
Компиляция и компоновка (MinGW64):
Bash
1
2
D:\Work>nasm -f win64 hello.asm -o hello.obj
D:\Work>x86_64-w64-mingw32-gcc hello.obj -o hello.exe
Linux (x64)

Изменения:
- Параметры передаются через регистры. Целые числа/указатели в rdi, rsi, rdx, rcx, r8 и r9. Действительные xmm0-xxm7, остальное через стек.
- Если вызывается подпрограмма с переменным числом параметров, то в RAX указываем число использованных xmm-регистров!!!
- Префикс не нужен.
- Изменился формат объектных файлов.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
global main
extern printf
 
section .code
main:
        mov     rax, 0
        mov     rsi, [rsi]
        mov     rdi, msg
        call    printf
 
        mov     rax, 23
        ret
 
section .data
msg     db "Hello World!!!", 10
        db "My name is '%s'", 10, 0
Компиляция, компоновка:
Bash
1
2
~/work$ nasm -f elf64 hello.asm -o hello.o
~/work$ gcc hello.o -o hello
P.S.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
global main
extern wprintf
extern _setmode
 
section .code
main:
        push    0x20000 ; _O_U16TEXT
        push    1       ; stdout
        call    _setmode
        add     esp, 8
 
        push    msg
        call    wprintf
        add     esp, 4
        
        mov     eax, 0
        ret
 
section .data
msg     dw __utf16__(`Hello World!!! \u263a`), 10
        dw __utf16__(`Привет мир!!!`), 10
        dw __utf16__(`Hello, \u4e16\u754c!!!`), 10, 0
Что бы увидеть последние два символа, запустите программу из ConEmu
0
Charles Kludge
Клюг
7637 / 3152 / 364
Регистрация: 03.05.2011
Сообщений: 8,382
16.09.2014, 16:36 #30
Цитата Сообщение от AlexVRud Посмотреть сообщение
Этот пост я направляю в первую очередь преподавателям и учителям.
Как-то борзо.
0
16.09.2014, 16:36
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.09.2014, 16:36
Привет! Вот еще темы с ответами:

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

Составить программу вывода на экран слова "Привет" - Assembler
1.Составить программу вывода на экран слова «Привет!». Желательно с пояснениями...

Заменить в строке группу символов "123" на "!", результат вывести на экран - Assembler
Помогите решить задачу. Ввести с клавиатуры строку. Заменить группу символов &quot; 123 &quot; на &quot; ! &quot;. Результат вывести на...

Вводят строку. Найти в ней все слова с буквой "Z" и переместить их в другую строку. Вывести новую строку - Assembler
Недавно начал изучать этот язык. Было все не плохо, но тут учитель решил поставить меня в тупит такой задачей... Вводят строку. Найти в...


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

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

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