1

how can i make an isalpha in nasm that takes the argv0 and prints it just in case it isalpha returns true, ie it contains letters, but i do not want to modify or delete what is not letters.

I found some cases here in the stackoverflow, but I was not able to modify them to start, since I'm a beginner in assembly.

ISALPHA EXAMPLE I SAW

Please, could you help me use this code along with a print using pure nasm, without c functions.

I also made this example code, I do not know if it is usable section .text
global _start

    _start:                                                                                                                                       
            push ebp                                                                                                                              
            mov ebp, esp                                                                                                                          

            mov ebx, [ebp+12]                                                                                                                     
            cmp ebx, 0x00                                                                                                                         
            jz exit                                                                                                                               
            mov eax, ebx                                                                                                                          

    strlen:                                                                                                                                       

            cmp byte [eax], 0x00                                                                                                                  
            jz result
            inc eax
            jmp strlen

    result:

            sub eax, ebx
            mov ecx, eax

    isalpha:

            mov dl, [ebx]
            or dl, 0x20
            sub dl, 'a'
            cmp dl, 'z'-'a'
            jna print
            inc ebx
            dec ecx
            jnz isalpha

    print:

            lea edx, [eax+1]
            mov ecx, ebx
            mov BYTE [ecx+eax], 0xA
            mov ebx, 0x1
            mov eax, 0x4
            int 0x80

    exit:
            mov eax, 0x1
            mov ebx, 0x0
            int 0x80
  • The C function `isalpha` takes *one* character, not a string. It seems you're talking about a version that loops over a whole string and requires all the characters to be alphabetic? Anyway, `ischar` is a terrible name for your loop, because (almost) every byte is a character. – Peter Cordes Jan 28 '19 at 02:48
  • Also, the code you copied from my answer on that other question isn't just checking `isalpha(c)`, it's case-flipping alphabetic character and leaving the rest unmodified. The isalpha part is just the OR/SUB/CMP to set flags according to whether or not the ASCII character is in A-Z or a-z ranges. – Peter Cordes Jan 28 '19 at 02:54
  • I Just want a isalpha version that ensures that the string have a alphabetic char, not everything needs to be alphabetic. – GunsReloaded Jan 28 '19 at 02:56
  • And you want to print the whole string if it contains any alphabetic character? Ok, then you'll want to loop over the string, and if you find an alphabetic character before getting to the end of the string, jump to the block of code that prints the whole string. (Put the `write` system call outside the loop, not in the middle where you have to jump over it.) I guess you'll have to keep looping to find the end of the string, though, because sys_write needs a length. – Peter Cordes Jan 28 '19 at 02:59
  • Ok, i think i need examples – GunsReloaded Jan 28 '19 at 03:03
  • First think about how you'd write it in C, using the C library `isalpha(3)` and `write(2)` functions. (And `strlen(3)` if you want). You know how to do that, right? – Peter Cordes Jan 28 '19 at 03:05
  • https://imgur.com/a/Q7oNEMA – GunsReloaded Jan 28 '19 at 03:13
  • First of all, semi-transparent images of code with other crap underneath are not a good way to communicate. But yes, that C snippet should work. Putting the `if()` inside the loop makes it weird, but then you have a `return 0` at the end of the if block so the loop doesn't keep running after you find the first one. – Peter Cordes Jan 28 '19 at 03:27
  • Well I tried it, I tried it myself, if anyone can help me understand what the problem with my code, I appreciate it, I'm extremely new to the assembly and I really do not understand what to do now – GunsReloaded Jan 28 '19 at 18:54
  • Try it in a debugger, and notice that it case-flips each alphabetic character because you still didn't take that out of your code. Also, `sys_write(int fd, char *buf, size_t len)` takes a *pointer* as the 2nd arg, not a character. So you need ECX=address of the string, not a 4-byte load from wherever you are in the string. Also, remember in your C version, you need to `return 0;` after you decide once to print the whole string? You're not doing that here, so at best if you fixed that attempt to `write` 1 char at a time, you'd be filtering the string to print only alphabetic chars. – Peter Cordes Jan 28 '19 at 19:28

1 Answers1

0

Well, initially I wanted a code that would check if the input satisfies isalpha() and if it do, print it "without modifying what is not alpha", but in I came to the conclusion, it is better to remove even that which is not alphabetic, for the sake of testing.

here is the C code I used as a skeleton:

#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp) {
    if (argv[1] == NULL) {
            printf("usage: %s string\n", argv[0]);
            return 1;
    }
    for (int c = 0; c < strlen(argv[1]); c++)
    {
       if (isalpha(argv[1][c]))
       {
            write(1, argv[1] + c, 1);
       }
    }
    write(1, "\n", 1);
    return 0;
}

and the assembly code that I came up with as a result, I'm extremely beginner in assembly, like 1 month learning a few things, so I'll be extremely grateful for suggestions of things I could do better or different

section .text                                                                                                                            [25/1709]
global _start                                                                                                                                     

_start:                                                                                                                                           

    push 0                                                                                                                                        
    mov ebp, esp                                                                                                                                  

    mov ebx, [ebp+12]                                                                                                                             
    cmp ebx, 0x00                                                                                                                                 
    jz exit                                                                                                                                       
    mov ecx, ebx                                                                                                                                  

strlen:                                                                                                                                           

    cmp byte [ecx], 0x00                                                                                                                          
    jz result                                                                                                                                     
    inc ecx                                                                                                                                       
    jmp strlen                                                                                                                                    

result:                                                                                                                                           

    sub ecx, ebx                                                                                                                                  

isalpha:                                                                                                                                          

    mov eax, [ebx]

    or al, 0x20
    sub al, 'a'
    cmp al, 'z'-'a'
    ja notalpha
    add al, 'a'

    push ecx
    push ebx
    push eax

    mov edx, 0x01
    mov ecx, esp
    mov ebx, 0x01
    mov eax, 0x04
    int 0x80

    pop eax
    pop ebx
    pop ecx

notalpha:

    inc ebx
    dec ecx
    jnz isalpha

exit:

    mov eax, 0x01
    mov ebx, 0x00
    int 0x80

note that in the assembly code case, unlike C one, the letters are all converted to lower-case in the output, I could not manage this out and I'll be grateful if anyone can do this correction so the assembly code do not change the letters case in the output.


  • You already have the original character in memory (pointed to by EBX), so pass `write` a pointer to that. If you keep your pointer in ECX instead, that's already the right register for sys_write with `int 0x80`. But in the general case, just copy something to another register before you destroy it, if you still want the original later. – Peter Cordes Jan 31 '19 at 04:33
  • What I did was put the ebx in the ecx, at the time of the print, thank you got it now. – GunsReloaded Jan 31 '19 at 15:39
  • If you still use EBX for the pointer, then you still have to save/restore it around `int 0x80` because you need EBX = fd = 1. Choose you register allocations so you don't need to push/pop around `int 0x80`. (Of course, calling `write` separately for every character is *very* slow, compare to what you were originally asking: deciding whether to print the whole string or not, then making one write call. Or to reproduce the result of this version, make a filtered copy of the string containing only the alphabetic characters. – Peter Cordes Feb 01 '19 at 00:58