Resultados 1 a 3 de 3
  1. #1
    Moderador Avatar de _Guga_
    Data de Ingresso
    Apr 2006
    Localização
    Salvador - BA
    Posts
    2.118

    [explicação] pegar parâmetros por linha comando (16 bits DOS)

    opa tudo bom?

    milênios depois do meu ultimo tuto aqui...

    OBS: Estou utilizando o Assembly x86 na arquitetura IA-32 sintaxe Intel, montador nasm e linkador alink!

    bem vamos la, meu objetivo aqui é demonstrar como funciona a "captura" de parametros por linha de comando. Para quem n sabe ou nunca ouviu falar, parametros de linha de comando são os "pós-fixos" do nome de um programa.

    Ex:

    ping -n 1 localhost
    estamos enviado os parametros "-n", "1" e "localhost" para o comando externo ping
    (externo porque na verdade ele eh um arquivo nativo localizado na pasta system32)

    no C e no C++, esses parametros são facilmente capturados e "parseados" pelos argumentos
    da função main, são eles um inteiro comumente denominado argc e uma matriz de caracteres,
    podendo ser char** ou char* [], comumente chamada argv. Sendo que o argc representa
    o tamanho da linha de comando (incluindo o nome do arquivo e ignorando-se os espaços) e o argv todos os caracteres digitados na linha de comando, ignorando-se os espaços e incluindo na primeira posição o nome do próprio programa.

    Em um programa DOS para realizarmos essa mesma tarefa, ja deixo claro que não é uma coisa muito complexa, pelo contrário, consome "poucas" linhas e funciona de forma similiar à do C e C++, ou seja, basicamente irão existir um contador, para armazenar o tamanho da linha de comando (excluindo o nome do arquivo e levando em consideração os espaços), e uma matriz de 2 nibbles (1 byte) contendo os caracteres digitados ( excluindo o nome do arquivo e levando em consideração os espaços ).

    logo, se eu criar um programinha asm e digitar na linha de comando:

    meuprograminha la lala

    o "contador" será atribuido ao tamanho do "pós-fixo" do programa, ou seja 7. E a matriz conterá os caracteres
    na sua forma ASCII:

    Matriz:

    108
    97
    32
    108
    97
    108
    97

    Count:

    7 Chars
    sendo 108 == 'l', 97 == 'a' e 32 == ' '

    Segundo o PSP (Program Segment Prefixe), o endereço de memória 80 armazena o número de caracteres da linha de comando, ou seja, será o nosso Argc, no caso de termos passado os parametros "la lala", ele terá o valor 7. A partir do endereço 82 em diante, estão os caracteres passados como parâmetro (incluindo espaços e não levando em consideração o nome do programa.

    Pondo em prática

    Criei um programa que apenas joga na output os parametros passados a ele, usando o serviço 2 da interrupção 21.

    Código:
    [SECTION CODE USE16 CLASS=CODE]  ; Meu cabeçalho, se quiserem por SEGMENT code tmb vale
    
    ..start:
        
        mov si, 0x80       ; Aqui fazemos o registrador Source Index apontar para o endereço 80
        
        lodsb                  ; o lodsb faz o que seu nome sugere, ele carrega um byte (tamanho da command line) armazenado nesse endereço, e joga em al
       
        cbw                    ; cbw ( Convert Byte to Word ), é opcional, apenas quero expandir al para ax
        
        mov cx, ax           ; movo ax, que agora armazena o tamanho da command line, para o registrador cx
        
        
        mov si, 0x82        ; agora fazemos o registrador SI apontar para o endereço 82
    
        xor ax, ax            ; limpo registrador ax, para manter a consciencia limpa mesmo =)
        
        looping:               ; label looping, onde iremos capturar os dados
    
            mov ah, 0x2     ; escolho o serviço para exibir caracteres isolados ( no caso o 2 )
            
            mov dl, byte[si]  ; movo o byte ( que representa o caractere ASCII ) que esta armazenado na posição atual de si,  para dl
            
            int 0x21         ; chamo a interrupção 21 e exibo o caractere
            
            inc si             ; passo para a proxima posição
            
            loop looping     ; decrementa cx e reitera o laço, findando apenas quando cx for nulo =)
        
         mov ax, 0x4C00           ; serviço 4C
         int 0x21                 ; chamo a 21 e finalizo
    simples não?

    caso vc queira usar os espaços para separar os argumentos, basta implementarmos um parser para isso. Caso queira ignorar os espaços, criamos um parser que continue incrementando sem fazer nada, a cada 32 ( space ) que contiver em byte[si], como podemos ver abaixo:

    Código:
    push ax   ; salvamos ax, pra n sobreescrevermos possiveis dados importantes
    
    mov ax, cx  ; jogamos tamanho da commandline em ax
    
    Verify:
    
       or ax, ax
       jz end_verify
    
       RMV_SPACE:
            
           cmp byte [si], 0x20  ; verificamose se o caractere atual é um space ( ASCII 0x20 -> 32 )       
           jne RMV_END     ; Caso não seja, saia do loop
           inc si ; senão incremente si
           dec cx ; e decremente cx ou seja o tamanho da command line
           jmp RMV_SPACE  ; reitere o loop
    
       RMV_END:
    
       dec ax
    
    jmp Verify
    
    end_verify:
    
    pop ax           ;   retomamos ax
    mov si, 0x82    ; retomamos o endereço inicial da linha de comando
    bem pessoal, sei que não sou nenhum profissional para redigir um tutorial nota 10, mas espero que meu "esforço" tenha valido a pena, pois se tem algo que eu gosto é de compartilhar o que eu sei e aprender com o maximo de modestia com todos.

    espero que tenham gostado e que eu tenha tirado um peso de alguém

    grande abraço


    I must not fear. Fear is the mind killer.

  2. #2
    Hacker Avatar de FoXxD
    Data de Ingresso
    Jun 2006
    Posts
    1.154
    Segundo o PSP (Program Segment Prefixe), o endereço de memória 80 armazena o número de caracteres da linha de comando, ou seja, será o nosso Argc, no caso de termos passado os parametros "la lala", ele terá o valor 7. A partir do endereço 82 em diante, estão os caracteres passados como parâmetro (incluindo espaços e não levando em consideração o nome do programa.
    Olá _Guga_
    Bela explicação, essa parte da explicação que citei acima é tudo.

  3. #3
    Gray Hat Avatar de CoderSc
    Data de Ingresso
    Jan 2011
    Localização
    #!/bin/bash
    Posts
    1.736
    Muito bem explicado parabens !!! ^^Flw !
    Når du føler flove over at se på tras eller bange for at se fremad, se venstre eller højre I be altid ved din side.

    H
    aters Gonna Hate

Permissões de Postagem

  • Você não pode iniciar novos tópicos
  • Você não pode enviar respostas
  • Você não pode enviar anexos
  • Você não pode editar suas mensagens
  •