How to ignore enter-key NASM win32
I figured out
I just wrote the code that removes 0x0d and 0x0a from the string
mov ecx,11; str len(and num of loop iterations)
mov eax,string
jmp ignore_enter
change_byte:
mov bl,0
mov byte[eax+ecx],bl;change byte to 0
ignore_enter:
cmp byte[eax+ecx], 0x0a; compare ecx byte of string with 0x0a
je change_byte; if equal change_byte
cmp byte[eax+ecx], 0x0D; compare ecx byte of string with 0x0d
je change_byte; if equal change_byte
loop ignore_enter
Remove Trailing Line-Breaking Characters from Read Input in Assembly
this isn't particulary elegant or efficient, but it might provide a starting point:
jcomeau@intrepid:/tmp$ cat test.nasm ; nasm -f elf -o test.o test.nasm; ld -o test test.o; ./test
section .bss
input: resb 255
.len: equ $ - input
section .text
global _start
_start:
;; Display message prompting for input, then...
mov edx, input.len
mov ecx, input
mov ebx, 0
mov eax, 3
int 0x80 ;read in from stdin
call rstrip
mov edx, eax ;count
mov ebx, 1 ;stdout
mov eax, 4
int 0x80 ;write out
mov eax, 1
xor ebx, ebx
int 0x80
rstrip:
dec eax ;convert 1-based length to 0-based pointer
.loop:
cmp byte [ecx + eax], 0xa
je .chop
cmp byte [ecx + eax], 0xc
je .chop
cmp byte [ecx + eax], 0xd
je .chop
.done:
inc eax ;convert pointer back to length
ret
.chop:
mov byte [ecx + eax], 0
dec eax
jns .loop
jmp .done
this is a test
this is a testjcomeau@intrepid:/tmp$
Change end of line character for user input in assembly
Assuming you're talking about Linux or OS X system calls for reading input from a Unix TTY, the normal way is to put the TTY in raw mode with ioctl so you see every character as its typed, no line-editing.
But you can also set the TTY's eol
(end of line) character. e.g. from the command line,
stty eol =
You can test it with cat
and see that =
(as well as newline) submit your buffered text to the kernel so cat sees it and prints it.
Use strace
to see what system calls stty
uses to do that. It's ioctl(0, TCGETS, { stuf ...}) = 0
(The stty sane
and/or reset
shell commands will reset your terminal settings back to normal after playing with stuff.)
Nasm print to next line
You have all the info already, you just don't see it yet:
resMsg db "Result: ", 0xA, 0xD
Do you know what this means exactly? It defines a string made of the following characters:
Result: XY
...where X
and Y
are actually invisible characters (with numerical values 0xA=10 and 0xD=13, also known as line feed (LF) and carriage return (CR)) which cause the output to wrap to a new line. They are specified outside of the doublequotes because of their invisible nature - you can't just include them there so you have to write their numerical values instead.
But of course you can use them alone as well:
newLineMsg db 0xA, 0xD
newLineLen equ $-newLineMsg
(newLineLen
will be 2 of course but I left it here to keep the system the same as you currently use, for easier understanding.)
So to just output a line break without any other text (what you want to do after the 5
), you can then use:
mov edx, newLineLen
mov ecx, newLineMsg
mov ebx, 1
mov eax, 4
int 0x80
...just like with resMsg
/resLen
.
However, as Jester pointed out, on Linux you should also be able to output just a single line feed (0xA) (and also remove the existing 0xD
's from your code).
NASM x86_64 Remove new line character and add 0 at the end of string
read
returns the number of characters, so you can index into the buffer and check if the last one read is a newline. Or just unconditionally overwrite it with 0
with this:
...
syscall ; rax = sys_read(0, buf, max_len)
mov byte [rsi + rax - 1], 0
That assumes no error and that the input string was submitted with a newline instead of EOF.
(Linux syscall
s preserve all regs except RAX (return value), and RCX/R11, so RSI still holds name
.)
x86 NASM Assembly - Problems with Input
Apart from what @Joshua is pointing out, you're not comparing your strings correctly.
checker:
mov ebx, check ; Moves the *address* of check into ebx
mov ecx, input ; Similarly for input
cmp ebx, ecx ; Checks if the addresses are the same (they never are)
Firstly, when you have e.g. label dd 1234
in your data segment mov eax, label
will move the address of label
to eax
while mov eax, [label]
will move the contents stored at label
(in this case 1234) into eax
.
Note that in the above example I deliberately used a 32-bit variable so that it would fit neatly into eax
. If you're using byte sized variables (like ascii characters) e.g. mybyte db 0xfe
you'll either have to use byte sized register (al
, ah
, dh
etc.) or use the move with zero/sign extend opcodes: movzx eax, byte [mybyte]
will set eax to 254, while movsx eax, byte [mybyte]
will set eax to -2 (0xfffffffe
).
You also need to do a character by character comparison of the strings. Assuming you save the read string length (you really should be checking for negative return values - meaning errors) in input_len
and check_len
it could look something like:
mov eax, [input_len]
cmp eax, [check_len]
jne loop ; Strings of different length, do loop again
mov ebx, check
mov ecx, input
.checkloop:
mov dl, [ebx] ; Read a character from check
cmp dl, [ecx] ; Equal to the character from input?
jne loop ; Nope, jump to `loop`
inc ebx ; Move ebx to point at next character in check
inc ecx ; and ecx to next character in input
dec eax ; one less character to check
jnz .checkloop ; done?
; the strings are equal if we reach this point in the code
jmp done
If you're interested in another way of doing this in fewer instructions look up rep cmpsb
.
There are a few other problems in the code immediately following your checker
code. The pop edx
instruction (and the code following, down to the loop
label) will not be execute as you're always jumping either to loop
or done
.
jne loop ;if not the same go to input again
je done ;else go to the end
pop edx ; Will never be reached!
The reason you're getting funny characters is from newlineL: db $-newline
This should be equ
instead of db
or you should replace mov edx, newlineL
with movzx edx, byte [newlineL]
. Since newlineL
unlike the other *L
names refers to a variable and not a constant equ
mov edx, newlineL
will use the address of the newlineL
variable as the number of bytes to write, when you wanted it to be 1.
Nasm interrupt calls getting skipped and outputting multiple lines
I think what you've run into is the fact that sys_read
(from stdin) doesn't return until it sees a linefeed (the "enter" key). Only the one character you're looking for goes into your buffer (Choice), the linefeed stays in the OS's buffer (call it the "keyboard buffer"). When the next sys_read
comes along, it reads that linefeed into your next buffer (FirstOperand)... and carries on... Hilarity ensues!
The easy way to fix it would be to make those buffers resb 2
and make edx
2, and trust the user to enter only one key and then "enter"... each time... Then studiously ignore the second byte in each buffer.
A better way might be to "flush the buffer" - the OS's keyboard buffer, not the buffer you've just read into. When sys_read
returns, the number read is in eax
. If it's less than edx
, you should be good (it won't be, in this case). If it's equal (it shouldn't be greater), check to see if the last character is that linefeed. If it is, you're good. If not, there's more cruft in the OS's buffer (which will screw up your next sys_read
!). Read into a "dummy" buffer (in .bss
or on the stack), a byte at a time, until you find that linefeed - cmp byte [dummybuf], 0Ah
or so. Then you're ready to continue...
Such are the joys of raw sys_call programming. :)
You don't ask, but mov [Answer], eax
could be asking for trouble. This will write to your one-byte buffer... and the three bytes after it! There's nothing after it, and it isn't butted up against memory you don't "own", so it won't cause a problem right now, but it's a "bug waiting to happen". Either use al
(should work here), or make Answer resd
so it'll fit all of eax
This isn't going to give you the answer you expect. You need to subtract '0' (or 30h or 48) from each operand before you do arithmetic on 'em, and then add '0' back to the answer before you print it. With nore than one digit, it's even worse! Get the interrupts working as intended first.
Assembly x86 NASM - Avoid read return key
One option is to flush the stdin buffer:
section .data
opA: db 0
opB: db 0
LF: db 10
section .text
global _start
_start:
inputA:
mov EAX, 3
mov EBX, 0
mov ECX, opA
mov EDX, 1
int 80h
mov eax,54 ; kernel function SYS_IOCTL
mov ebx,0 ; EBX=0: STDIN
mov ecx,0x540B ; ECX=0x540B: TCFLSH
xor edx, edx ; EDX=0: TCIFLUSH
int 0x80 ; sys_call
inputB:
mov EAX, 3
mov EBX, 0
mov ECX, opB
mov EDX, 1
int 80h
mov eax,54 ; kernel function SYS_IOCTL
mov ebx,0 ; EBX=0: STDIN
mov ecx,0x540B ; ECX=0x540B: TCFLSH
xor edx, edx ; EDX=0: TCIFLUSH
int 0x80 ; sys_call
print:
mov edx,3
mov ecx,opA
mov ebx,1
mov eax,4
int 0x80
exit:
mov eax, 1
mov ebx, 0
int 0x80
Another option - which works with pipes - is to read stdin until EOF or LF:
section .data
opA: db 0
opB: db 0
LF: db 10
dummy: db 0
section .text
global _start
reads:
.1: ; Loop
mov eax,3 ; kernel function SYS_READ
mov ebx, 0 ; EBX=0: STDIN
mov ecx, dummy ; dummy buffer
mov edx, 1 ; number of bytes to read
int 0x80 ; sys_call
test eax, eax ; EOF?
jz .2 ; yes: ok
mov al,[dummy] ; no: fetched character
cmp al, 10 ; character == LF ?
jne .1 ; no -> loop (i.e. fetch next character)
.2
ret
_start:
inputA:
mov EAX, 3
mov EBX, 0
mov ECX, opA
mov EDX, 1
int 80h
call reads
inputB:
mov EAX, 3
mov EBX, 0
mov ECX, opB
mov EDX, 1
int 80h
call reads
print:
mov edx,3
mov ecx,opA
mov ebx,1
mov eax,4
int 0x80
exit:
mov eax, 1
mov ebx, 0
int 0x80
Related Topics
Using Bash Environment Variables from Within a Perl Script
Best Posix Way to Determine If a Filesystem Is Mounted Read Only
Jboss as 7.1.1 Ejb 3:Ejb Pool Error
Extending a Script to Loop Over Multiple Files and Generate Output Names
Rename Files and Directories (Add Prefix)
How to Request a File But Not Save It with Wget
Split Output of Command by Columns Using Bash
Remove Only Files in Directory on Linux Not Directories
How to Export Dbus_Session_Bus_Address
Is There Any Method to Run Perf Under Wsl
Gcc: Putchar(Char) in Inline Assembly
Why Does the Wc Command Count One More Character Than Expected
Suppress Notice of Forked Command Being Killed
Why Do My Results Different Following Along the Tiny Asm Example
Signals and Interrupts a Comparison
Can You Attach Amazon Ebs to Multiple Instances
Mongodb Data Directory /Data/Db Not Found
Specify the from User When Sending Email Using the Mail Command