1 Востаннє редагувалося Vo_Vik (08.05.2013 15:59:02)

Тема: TASM Робота з файлами.

Тут недавно попросили для курсача написати програмку, то трохи посидів покодив під TASM
Може комусь пригодиться, коменти писав, так що не мало би бути проблем з розумінням як працює.

Завдання

Читає 20 символів з клавіатури, пише їх в файл. Читає з цього файла, якщо зустрічає ^,<,> пише наступні символи у файли m1,m2,m3 відповідно

Розв’язок
.model small
.stack 256

.data
    S0    DB    'Please enter your 20 chars', 13, 10, '$'
    S1    DB    'I could not open $'
    S2    DB    ' for writing.',13,10,'$'
    S3    DB    'I could not open $'
    S4    DB    ' for reading.',13,10, '$'
    S5    DB    '$'
    C2    DB    '^'
    C3    DB    '<'
    C4    DB    '>'
    FN1    DB    'm1.txt',0
    FN2    DB    'm2.txt',0
    FN3    DB    'm3.txt',0
    FN4    DB    'm4.txt',0
    US1    DB    20    dup    (20h)
    F1    DW    0
    F2    DW    0
    F3    DW    0
    F4    DW    0
.code

;*******************************************
main:
    MOV ax, @data
    MOV ds, ax
; print welcome message:
    LEA     DX, S0
    MOV     AH, 09h
    INT     21h
;============================
; Eternal loop to get
; and print keys:
    MOV CX, 20
    MOV SI,    0
wait_for_key:

; get keystroke from keyboard:
; (remove from the buffer)
    MOV     AH, 0
    INT     16h

;puts the characters in the array
    MOV [US1+SI], AL
    INC SI

; print the key:
    MOV     AH, 0Eh
    INT     10h

;check how many entered
    LOOP      wait_for_key

;create files
    MOV AH, 3CH
    MOV CL, 0
    LEA DX, FN1
    INT 21h 
    MOV F1, AX

    MOV AH, 3CH
    MOV CL, 0
    LEA DX, FN2
    INT 21h 
    MOV F2, AX

    MOV AH, 3CH
    MOV CL, 0
    LEA DX, FN3
    INT 21h
    MOV F3, AX

    MOV AH, 3CH
    MOV CL, 0
    LEA DX, FN4
    INT 21h 
    MOV F4, AX

;save string into file
    MOV AH, 40h
    MOV BX, F1
    MOV CX, 20
    LEA DX, US1
    INT 21h
;close file    
    MOV AH,3Eh
    INT 21h

;open file for reading
    MOV AH, 3CH
    MOV CL, 1
    LEA DX, FN1
    INT 21h 
    MOV F1, AX
;read from file
    MOV AH,3fh
    MOV BX,F1
    MOV CX,20
    LEA DX, US1
    INT 21h
;close file    
    MOV AH,3Eh
    INT 21h

;analize string
    MOV SI,    0
    MOV BX, 0
next_char:
    MOV AL, [US1+SI]
;look for comand chars
    CMP AL, [C2+0]
    JE set_F2
    CMP AL, [C3+0]
    JE set_F3
    CMP AL, [C4+0]
    JE set_F4
    CMP BX, 0
    JE loop_check
;save this char
    MOV S5, AL
    JMP save_in_file
set_F2:
    MOV BX, F2
    JMP loop_check
set_F3:
    MOV BX, F3
    JMP loop_check
set_F4:
    MOV BX, F4
    JMP loop_check
save_in_file:
    MOV AH, 40h
    MOV CX, 1
    LEA DX, S5
    INT 21h
loop_check:
    INC SI
    CMP SI,20
    JL next_char

;close all files
    MOV BX, F2    
    MOV AH,3Eh
    INT 21h
    MOV BX, F3    
    MOV AH,3Eh
    INT 21h
    MOV BX, F4    
    MOV AH,3Eh
    INT 21h
    
; return to operating system:
exit:
    MOV     AH, 4Ch
    INT     21h
end main
Подякували: Replace1

2

Re: TASM Робота з файлами.

Доречі, ось що мені видав компілятор сішки, так для порівння швидкодії високорівневого програмування

Прихований текст
    .file    "test.c"
    .section    .rodata
.LC0:
    .string    "Please enter your 20 chars"
.LC1:
    .string    "w"
.LC2:
    .string    "m1"
    .align 4
.LC3:
    .string    "I couldn't open %s for writing.\n"
.LC4:
    .string    "%s\n"
.LC5:
    .string    "r"
    .align 4
.LC6:
    .string    "I couldn't open %s for reading.\n"
.LC7:
    .string    "m2"
.LC8:
    .string    "m3"
.LC9:
    .string    "m4"
.LC10:
    .string    "a"
.LC11:
    .string    "\n"
    .text
    .globl    main
    .type    main, @function
main:
.LFB0:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $64, %esp
    movl    %gs:20, %eax
    movl    %eax, 60(%esp)
    xorl    %eax, %eax
    movl    $.LC0, (%esp)
    call    puts
    movl    stdin, %eax
    movl    %eax, 8(%esp)
    movl    $20, 4(%esp)
    leal    40(%esp), %eax
    movl    %eax, (%esp)
    call    fgets
    movl    $.LC1, %edx
    movl    $.LC2, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 28(%esp)
    cmpl    $0, 28(%esp)
    jne    .L2
    movl    $.LC3, %eax
    movl    $.LC2, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $0, (%esp)
    call    exit
.L2:
    movl    $.LC4, %eax
    leal    40(%esp), %edx
    movl    %edx, 8(%esp)
    movl    %eax, 4(%esp)
    movl    28(%esp), %eax
    movl    %eax, (%esp)
    call    fprintf
    movl    28(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $.LC5, %edx
    movl    $.LC2, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 28(%esp)
    cmpl    $0, 28(%esp)
    jne    .L3
    movl    $.LC6, %eax
    movl    $.LC2, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $0, (%esp)
    call    exit
.L3:
    movl    $.LC4, %eax
    leal    40(%esp), %edx
    movl    %edx, 8(%esp)
    movl    %eax, 4(%esp)
    movl    28(%esp), %eax
    movl    %eax, (%esp)
    call    __isoc99_fscanf
    movl    28(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $.LC1, %edx
    movl    $.LC7, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 32(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $.LC1, %edx
    movl    $.LC8, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 32(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $.LC1, %edx
    movl    $.LC9, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 32(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $0, 24(%esp)
    jmp    .L4
.L9:
    leal    40(%esp), %eax
    addl    24(%esp), %eax
    movzbl    (%eax), %eax
    cmpb    $94, %al
    jne    .L5
    movl    $.LC7, %edx
    leal    38(%esp), %eax
    movzwl    (%edx), %ecx
    movw    %cx, (%eax)
    movzbl    2(%edx), %edx
    movb    %dl, 2(%eax)
    jmp    .L6
.L5:
    leal    40(%esp), %eax
    addl    24(%esp), %eax
    movzbl    (%eax), %eax
    cmpb    $62, %al
    jne    .L7
    movl    $.LC8, %edx
    leal    38(%esp), %eax
    movzwl    (%edx), %ecx
    movw    %cx, (%eax)
    movzbl    2(%edx), %edx
    movb    %dl, 2(%eax)
    jmp    .L6
.L7:
    leal    40(%esp), %eax
    addl    24(%esp), %eax
    movzbl    (%eax), %eax
    cmpb    $60, %al
    jne    .L8
    movl    $.LC9, %edx
    leal    38(%esp), %eax
    movzwl    (%edx), %ecx
    movw    %cx, (%eax)
    movzbl    2(%edx), %edx
    movb    %dl, 2(%eax)
    jmp    .L6
.L8:
    movzbl    38(%esp), %eax
    cmpb    $109, %al
    jne    .L6
    movl    $.LC10, %edx
    leal    38(%esp), %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 32(%esp)
    leal    40(%esp), %eax
    addl    24(%esp), %eax
    movzbl    (%eax), %eax
    movsbl    %al, %eax
    movl    32(%esp), %edx
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fputc
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
.L6:
    addl    $1, 24(%esp)
.L4:
    cmpl    $19, 24(%esp)
    jle    .L9
    movl    $.LC10, %edx
    movl    $.LC7, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 32(%esp)
    leal    40(%esp), %eax
    addl    24(%esp), %eax
    movzbl    (%eax), %eax
    movsbl    %al, %edx
    movl    $.LC11, %eax
    movl    %edx, 8(%esp)
    movl    %eax, 4(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fprintf
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $.LC10, %edx
    movl    $.LC8, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 32(%esp)
    leal    40(%esp), %eax
    addl    24(%esp), %eax
    movzbl    (%eax), %eax
    movsbl    %al, %edx
    movl    $.LC11, %eax
    movl    %edx, 8(%esp)
    movl    %eax, 4(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fprintf
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $.LC10, %edx
    movl    $.LC9, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    fopen
    movl    %eax, 32(%esp)
    leal    40(%esp), %eax
    addl    24(%esp), %eax
    movzbl    (%eax), %eax
    movsbl    %al, %edx
    movl    $.LC11, %eax
    movl    %edx, 8(%esp)
    movl    %eax, 4(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fprintf
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    fclose
    movl    $0, (%esp)
    call    exit
    .cfi_endproc
.LFE0:
    .size    main, .-main
    .ident    "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

3

Re: TASM Робота з файлами.

В цілому погоджуюся, що програми на ассемблері мають потенціал ефективності; але:
- код написаний для різних процесорів і систем;
- код на C використовує значно потужніші засоби, чому б не скористатися fgets і fputs, як в асемблері?
- незрозуміло, який рівень оптимізації задіяно в останній програмі.

До речі, чому в останньому тексті аж 9 fclose? Це якісь особливості компілятора? Можна сирцевий код на С глянути?

4

Re: TASM Робота з файлами.

Оце вроді
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NUM 20
#define FILE1 "m1"
#define FILE2 "m2"
#define FILE3 "m3"
#define FILE4 "m4"
#define CHAR2 "^"
#define CHAR3 ">"
#define CHAR4 "<"

int main() {
 char symbols[NUM], filename[2];
 FILE *f1, *f2;
 int i;
 printf("Please enter your 20 chars\n");
 fgets(symbols, NUM, stdin);
 f1 = fopen(FILE1, "w");
 if (f1 == NULL) {
  printf("I couldn't open %s for writing.\n", FILE1);
  exit(0);
 }
 fprintf(f1, "%s\n", symbols);
 fclose(f1);
 f1 = fopen(FILE1, "r");
 if (f1 == NULL) {
  printf("I couldn't open %s for reading.\n", FILE1);
  exit(0);
 } 
 fscanf(f1, "%s\n", symbols);
 fclose(f1);
 f2 = fopen(FILE2, "w");
 fclose(f2);
 f2 = fopen(FILE3, "w");
 fclose(f2);
 f2 = fopen(FILE4, "w");
 fclose(f2);
 for(i=0; i<20; i++){
  if(symbols[i]=='^')
   strcpy(filename, FILE2);
  else if(symbols[i]=='>')  
   strcpy(filename, FILE3);
  else if(symbols[i]=='<')  
   strcpy(filename, FILE4);
  else if(filename[0]=='m'){
   f2 = fopen(filename, "a");
   fprintf(f2, "%c", symbols[i]);
   fclose(f2);
  }
 }
 f2 = fopen(FILE2, "a");
 fprintf(f2, "\n", symbols[i]);
 fclose(f2);
 f2 = fopen(FILE3, "a");
 fprintf(f2, "\n", symbols[i]);
 fclose(f2);
 f2 = fopen(FILE4, "a");
 fprintf(f2, "\n", symbols[i]);
 fclose(f2);
 exit(0);
}

5 Востаннє редагувалося koala (08.05.2013 20:50:50)

Re: TASM Робота з файлами.

:facepalm: (додайте смайлик, він тут конче потрібен!)
А якби ви ще шукали мільйонне просте число і 100000 знаків Пі в цій задачі, код би був ще довший...

6

Re: TASM Робота з файлами.

Ви таки змусили мене продивитися ваш код ретельно - це ж мухльож, він не виводить повідомлень про помилку, на відміну від Сшного! Звісно, якщо один код робить вдвічі більше роботи, то він і буде вдвічі довшим за другий...
А ще код на C у вас UB-шний, ви не тримаєте для кінцевих нулів символів в масивах.

7 Востаннє редагувалося koala (08.05.2013 22:04:24)

Re: TASM Робота з файлами.

Ось вам код C
#include <stdio.h>
 
#define NUM 20
#define FILE0 "m0"
#define FILE1 "m1"
#define FILE2 "m2"
#define FILE3 "m3"
#define CHAR1 '^'
#define CHAR2 '>'
#define CHAR3 '<'

int main() {
  FILE *source, *t1, *t2, *t3, *target;
  int i;
  char c;
  source = fopen( FILE0, "w" );
  printf("Please enter your 20 chars\n");
  for( i = 0; i < NUM; i++)
    fputc( getchar(), source );
  fclose(source);
  
  source = fopen(FILE0, "r");
  t1 = fopen(FILE1, "w");
  t2 = fopen(FILE2, "w");
  t3 = fopen(FILE3, "w");
  target = NULL;

  for( i = 0; i < NUM; i++ )
  {
    c = fgetc( source );
    switch(c)
    {
      case CHAR1:
        target = t1;
      break;
      case CHAR2:
        target = t2;
      break;
      case CHAR3:
        target = t3;
      break;
      default:
          if( target != NULL )
          fputc( c, target );
    }
  }
  fclose(source);
  fclose(t1);
  fclose(t2);
  fclose(t3);
}
А ось вам згенерований асемблерний код
    .file    "aaa.c"
    .def    __main;    .scl    2;    .type    32;    .endef
    .section .rdata,"dr"
.LC0:
    .ascii "w\0"
.LC1:
    .ascii "m0\0"
.LC2:
    .ascii "Please enter your 20 chars\0"
.LC3:
    .ascii "r\0"
.LC4:
    .ascii "m1\0"
.LC5:
    .ascii "m2\0"
.LC6:
    .ascii "m3\0"
    .text
    .globl    main
    .def    main;    .scl    2;    .type    32;    .endef
    .seh_proc    main
main:
    pushq    %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    subq    $96, %rsp
    .seh_stackalloc    96
    .seh_setframe    %rbp, 96
    .seh_endprologue
    call    __main
    leaq    .LC0(%rip), %rdx
    leaq    .LC1(%rip), %rax
    movq    %rax, %rcx
    call    fopen
    movq    %rax, -24(%rbp)
    leaq    .LC2(%rip), %rcx
    call    puts
    movl    $0, -12(%rbp)
    jmp    .L2
.L3:
    call    getchar
    movq    -24(%rbp), %rdx
    movl    %eax, %ecx
    call    fputc
    addl    $1, -12(%rbp)
.L2:
    cmpl    $19, -12(%rbp)
    jle    .L3
    movq    -24(%rbp), %rax
    movq    %rax, %rcx
    call    fclose
    leaq    .LC3(%rip), %rdx
    leaq    .LC1(%rip), %rax
    movq    %rax, %rcx
    call    fopen
    movq    %rax, -24(%rbp)
    leaq    .LC0(%rip), %rdx
    leaq    .LC4(%rip), %rax
    movq    %rax, %rcx
    call    fopen
    movq    %rax, -32(%rbp)
    leaq    .LC0(%rip), %rdx
    leaq    .LC5(%rip), %rax
    movq    %rax, %rcx
    call    fopen
    movq    %rax, -40(%rbp)
    leaq    .LC0(%rip), %rdx
    leaq    .LC6(%rip), %rax
    movq    %rax, %rcx
    call    fopen
    movq    %rax, -48(%rbp)
    movq    $0, -8(%rbp)
    movl    $0, -12(%rbp)
    jmp    .L4
.L10:
    movq    -24(%rbp), %rax
    movq    %rax, %rcx
    call    fgetc
    movb    %al, -49(%rbp)
    movsbl    -49(%rbp), %eax
    cmpl    $62, %eax
    je    .L7
    cmpl    $94, %eax
    je    .L8
    cmpl    $60, %eax
    je    .L6
    jmp    .L11
.L8:
    movq    -32(%rbp), %rax
    movq    %rax, -8(%rbp)
    jmp    .L9
.L7:
    movq    -40(%rbp), %rax
    movq    %rax, -8(%rbp)
    jmp    .L9
.L6:
    movq    -48(%rbp), %rax
    movq    %rax, -8(%rbp)
    jmp    .L9
.L11:
    cmpq    $0, -8(%rbp)
    je    .L9
    movsbl    -49(%rbp), %eax
    movq    -8(%rbp), %rdx
    movl    %eax, %ecx
    call    fputc
.L9:
    addl    $1, -12(%rbp)
.L4:
    cmpl    $19, -12(%rbp)
    jle    .L10
    movq    -24(%rbp), %rax
    movq    %rax, %rcx
    call    fclose
    movq    -32(%rbp), %rax
    movq    %rax, %rcx
    call    fclose
    movq    -40(%rbp), %rax
    movq    %rax, %rcx
    call    fclose
    movq    -48(%rbp), %rax
    movq    %rax, %rcx
    call    fclose
    addq    $96, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .def    puts;    .scl    2;    .type    32;    .endef
    .def    fopen;    .scl    2;    .type    32;    .endef
    .def    getchar;    .scl    2;    .type    32;    .endef
    .def    fputc;    .scl    2;    .type    32;    .endef
    .def    fclose;    .scl    2;    .type    32;    .endef
    .def    fgetc;    .scl    2;    .type    32;    .endef