MASM StrCmp Undefined? - string

If I try to assemble the following code, I get a A2006 error ( error A2006: undefined symbol : StrCmp).
Here's my code:
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\stdlib.lib
includelib \masm32\lib\user32.lib
.data
YvanSoftware db "(c) YvanSoftware - ALL RIGHTS RESERVED", 13 ,10 ,0
EnterYourName db "Please enter your name: ", 0
CRLF db 13,10,0
TheHolyMan db "Yvan", 0
Seriously db "Seriously? You're the MAN!", 13,10,0
LoserName db "What a loser name.", 13,10
.data?
buffer db 100 dup(?)
.code
start:
invoke StdOut,addr YvanSoftware
invoke StdOut, addr EnterYourName
invoke StdIn, addr buffer, 100
invoke StdOut, addr CRLF
invoke StrCmp,addr buffer, addr TheHolyMan ;error fires here
je HolyMan
IfNotHolyMan:
invoke StdOut, addr LoserName
jmp EndIfHolyMan
HolyMan:
invoke StdOut, addr Seriously
jmp EndIfHolyMan
EndIfHolyMan:
invoke ExitProcess,0
END start
I'm a complete n00b at assembler, and I'm trying to learn it. ;)
Yvan

You do not mention any error on the invoke StdOut, so I assume this one assembles. In this case, the error should be exactly what it says: StrCmp is not recognized in the include files you listed. So just make sure one of your includes actually defines StrCmp (and since I don't remember what mode MASM defaults to, respect case sensitivy to be on the safe side).
Since You are using stdcall, your invoke will gen an external reference to something like _StrCmp#8 (#8 because there are two parms, each being 4 bytes). So you will also need to have this decorated name present in one of the includelib libs. This is not the problem you are seeing though, as this error is a masm one rather than a linker one.

Related

Print values of variables on a line (without new line) [duplicate]

This question already has answers here:
Printf without newline in assembly
(5 answers)
Printing an entire array on a single line using printf asm nasm
(3 answers)
Closed 2 years ago.
So, i faced with a problem, that print each value of variable on a new line, but format for print is a line. I really spend a lot of time that find solution. But this solution don't work. I think that is because i am noob in assembler. So, i deleted all my fail... This is my code:
global main
extern printf
section .data
str: db "%i", 10, 0
count: dw 1
section .text
main:
start:
push dword [count]
push dword str
call printf
push dword [count]
push dword str
call printf
So, now in terminal printed this:
1
1
What do I need to do to print like this:
1 1
Please, example me code, that i understand.... Please, don't send me first link in internet with similar problem, because i tried this. I really don't understand...
How i can insert in print string with differents char, for example ':', 'space', '/' and other...?
Thanks you :)
Change
str: db "%i", 10, 0
to
str: db "%i ", 0
10 is a newline character. This replaces it with a space.

How do I count the number of characters in a string in NASM?

I want to take an input and display the input with how many characters are in the string.
So far I'm able to produce the string, but I'm confused as to how I get the input?
You can use this function:
count db 0; (or resb 1), this is the place where will stay the result
count_string:
lodsb; // load char( letter )
cmp al, 0x00; // check string end; cause 0x00 its not a letter or number, 0 is 30h in ascii
jz done; // count done
inc byte [count]; adds 1 to count register
jmp count_string; // check next char
done:
ret; // exit function
And you can define a string this way:
data:
; or in the section .data
string DB "This is my string", 0; 0 means the end of the string
you can call the function this way:
mov si, string; move the string pointer to register
call count_string;
and if you are using nasm inside a OS like windows or ubuntu uou can watch this: https://www.youtube.com/watch?v=VAy4FGHDx1I
but in x86 i did a 4 byte( for letters ) command line, its really easy to get much more but it was just a quick experiment i used int 16h( keyboard )

Register value followed by a capture group in a replace gives error

I'm trying to use vim to port an assembly language file to a new assembler. The new assembler does not support local labels. So I'm trying to insert the label name before each local label. But trying to use a register followed by a capture group causes an "Invalid expression error".
Example input:
LABEL_NAME:
MOV SP,#STACK_POINTER
MOV R7,#12 ;WAIT LOOP (3)
12$: MOV R6,#255 ;TIME WASTER
11$: MOV R5,#255 ;MUST WAIT !!!!
10$: RESET_WATCH_DOG
DJNZ R5,10$
DJNZ R6,11$
DJNZ R7,12$
Desired output:
LABEL_NAME:
MOV SP,#STACK_POINTER
MOV R7,#12 ;WAIT LOOP (3)
LABEL_NAME12$: MOV R6,#255 ;TIME WASTER
LABEL_NAME11$: MOV R5,#255 ;MUST WAIT !!!!
LABEL_NAME10$: RESET_WATCH_DOG
DJNZ R5,LABEL_NAME10$
DJNZ R6,LABEL_NAME11$
DJNZ R7,LABEL_NAME12$
This, of course, works:
:.,10s/\(\d\+\$\)/LABEL_NAME\1/
After yanking the label name into register a, this:
:.,10s/\(\d\+\$\)/\=#a/
Gives me this:
LABEL_NAME:
MOV SP,#STACK_POINTER
MOV R7,#12 ;WAIT LOOP (3)
LABEL_NAME: MOV R6,#255 ;TIME WASTER
LABEL_NAME: MOV R5,#255 ;MUST WAIT !!!!
LABEL_NAME: RESET_WATCH_DOG
DJNZ R5,LABEL_NAME
DJNZ R6,LABEL_NAME
DJNZ R7,LABEL_NAME
But this:
:.,10s/\(\d\+\$\)/\=#a\1/
Produces only this:
E15: Invalid expression: #a\1
I'm using gVim 7.3. Ideally I'd like to know why I can't use register expansion followed by capture group expansion in a replace statement. But alternative solutions would also be appreciated.
If you use expression in replacement part, you have to use expression in whole part, not hybrid expression. this should work:
:.,10s/\(\d\+\$\)/\=#a . submatch(1)/g
short explanation:
\= " the replacement will be expression
#a " read the value from register 'a'
. " the string concatenation
submatch(x) " (function) get the matched group from your :s command, x=0,1,2...
help item:
:h :s
:h submatch()

converting a decimal/hex value in a register to ascii

So say I have this value in a register ebx: 30303420
I want to convert that and print out the corresponding ascii values. So it SHOULD print out
004
30 == 0
30 == 0
34 == 4
20 == space character.
How would I get that to print on the screen?
This is 80x86 architecture, using assembly code.
Well, your question have a couple unclear details.
1- If you have 30303420 Hex value in ebx, then you have 4 Ascii characters, precisely "004 ", that is:
mov ebx,30303420H ;is exactly the same than:
mov ebx,"004 "
You have NOT any decimal value (wich one?), so there is not any conversion here.
2- If you want to show that ebx value in the screen, so it shows "004 ", then you must specify under which operating system your program will run in order to use the appropiate services. For example, if you want to use old-style MS-DOS INT 21H functions, that also run in a DOS Window in Windows, then this segment do that:
mov cx,4 ;counter = 4 characters
;
next:
rol  ebx,8 ;rotate left EBX 1 byte: place next char in BL
mov dl,bl ;DL = char to show
mov ah,2 ;AH = VIDEO OUTPUT function
int 21H  ;DOS kernel service Int: show the char
loop next ;repeat 4 times
However, if your program run under Linux, the method to show ebx value is entirely different. Also, your program may use a C library function in a different way, or be a Windows-compliant program, or use BIOS INT 10H service (in charge of the screen), or even directly access the video circuitry, etc, etc, etc...

What's the difference between %define and equ in NASM?

Code:
%define x 0x03
x equ 0x03
What's the difference between them?
%define is a far more powerful way of doing macros, akin to the C pre-processor. In your simplistic case, there is not a lot of difference, using x in the source code will result in the constant 3 being substituted. There's a subtle difference in that equ statements are evaluated once, when they are first read and %define macros are evaluated whenever they are encountered in the source.
You can see the difference there between the two statement snippets:
addr equ $
%define addr $
In that case, addr, when encountered in the code, will have different values. In the first case, $ will be the location of the assembly position at the place where the equ is. In other words, where it's defined.
In the second case, it evaluates to the assembly location at the place where addr is used.
Where %define shines is with something like:
%define thricexplusy(x,y) (3 * x + y)
or:
%define ctrl(c) (c & 0x1F)
: :
mov al, ctrl('z')
(or even considerably more complex things) which allow you to pass parameters to your macro, something not possible with a simple equ.

Resources