MS-DOS 6.22 variable trimming

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
cajunjon
Posts: 2
Joined: 01 Apr 2021 09:10

MS-DOS 6.22 variable trimming

#1 Post by cajunjon » 01 Apr 2021 11:00

I inherited a legacy MS-DOS 6.22 project which has an app that reads a CPU's IA32_PERF_STATUS Register, MSR 0x198, which then outputs a HEX value. I need to trim off everything right and left of the 29th and 30th characters (24 in this output). The outputted values will be different for different model CPU's.
I then need to convert that value to Decimal. The code below works in Windows but not in MS-DOS 6.22.
Here's what I tried without the HEX2DEC conversion. I found a MS-DOS 16bit HEX converter app at http://blog.code-cop.org/2008/07/dos-tools.html that can do the conversion as well.

@echo off
rdmsr.exe 0x198 > 198.txt
rem Expected output is "CPU_0 APIC_0 MSR 0x0198 = 0x24AB24AB 0x240024AB"
for /F "tokens=*" %%A in (198.txt) do set string=%%A
set /A perf=%string:~17,2%
@echo %perf%c

Any help would be appreciated.

jeb
Expert
Posts: 980
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: MS-DOS 6.22 variable trimming

#2 Post by jeb » 02 Apr 2021 06:23

Hi cajunjon,

you could split your problem into smaller problems and use some helper files.

The list of your problems
  1. You need to assign the program output to a variable
  2. Split a string into parts
  3. substring works only for strings without spaces or other delimiters
  4. A variable can't contain an equal sign (or I don't know how to assign it)
Problem 1 is easy to solve with a file containing only "SET var=" without any line feeds, see READ.BAT
call READ.BAT 198.txt line

Problem 2 can be solved with SUBSTR.BAT (requires INC.BAT)

Code: Select all

call READ.BAT 198.txt str
call SUBSTR.BAT 29 2 resutl
Problem 3 can be solved, if you take only the 5th word of your string by using a simple FOR loop, see SPLITSTR.BAT

Code: Select all

call READ.BAT 198.txt str
call SPLITSTR strparts
set str=%strparts[4]%
call SUBSTR.BAT 2 2 result
echo %result%
Only problem4 isn't solved yet, but the solution should be obvious :D

SUBSTR.BAT

Code: Select all

@echo off
rem Extract a substring from a string 
rem The input string has to be stored in "str"
rem @base index of the first character, 0 is the first
rem @length Take @length characters from index or stop at the string end
rem Usage: call substr @base @length @returnvar
rem Sample: call substr 2 6 result

for %%L in (/%0) do if "%%L"=="/" goto %1

:main
call %0// :split %1
set str=%_right%
call %0// :split %2
if "%3"=="" echo ["%_left%", "%_right%"]
if "%3"=="" goto :clear
set %3=%_left%

:clear
REM Clear temp vars
FOR %%v in (_left _right _idx _splitpos _finish _remain) do set %%v=
goto :eof

:split
if NOT %2==0 goto :process
  set _left=
  set _right=%str%
goto :eof

:process
set _left=
set _right=
set _idx=1
set _splitpos=%2
set _finish=0
set _remain=%str%

:loop
set _first=1
FOR %%a in (/%_remain%) DO call %0// :split_char %%a
if %_finish%==1 goto :eof
if NOT "%_remain%"=="" goto :loop
goto :eof

:split_char
if "%_first%"=="" goto :_second
if %_idx%==%_splitpos% set _finish=1
set _left=%_left%%2
call inc %_idx% _idx
set _first=
set _remain=
goto :eof

:_second
set _remain=%2
if %_finish%==1 set _right=%2
goto :eof

:eof
INC.BAT

Code: Select all

@echo off

for %%L in (/%0) do if "%%L"=="/" goto %1

REM Split and reverse number into _valueRev
set _remain=%1
set _valueRev=

:split_loop
set _loop=1

for %%a in (/%_remain%) do call %0// :split %1 %%a
if NOT "%_remain%"=="" goto :split_loop
goto :increment

:split
if %_loop%==2 goto :split_2
set _loop=2
set _remain=
set _valueRev=%3,%_valueRev%
goto :eof

:split_2
set _remain=%3
goto :eof

REM The main increment function
:increment
set _incresult=
set _carry=1
for %%d in (%_valueRev%) do call %0// :incDig %%d
if not "%_carry%"=="" call %0// :incDig 0

if NOT "%2"=="" set %2=%_incresult%
REM Clear temp vars
FOR %%v in (_incresult _carry _loop _valueRev _valueRev_comma _digit _remain) do set %%v=
goto :eof

:incDig
set _digit=%2
if "%_carry%"=="" goto :endinc
set _carry=
if %2==9 set _digit=0
if %2==9 set _carry=1
if %2==8 set _digit=9
if %2==7 set _digit=8
if %2==6 set _digit=7
if %2==5 set _digit=6
if %2==4 set _digit=5
if %2==3 set _digit=4
if %2==2 set _digit=3
if %2==1 set _digit=2
if %2==0 set _digit=1

:endinc
set _incresult=%_digit%%_incresult%
:eof
READ.BAT

Code: Select all

@echo off

type READ.HLP > TMP.BAT 
TYPE %1 >> TMP.bat
call TMP.bat
del tmp.bat
set %2=%_read%
set _read=
READ.HLP

Code: Select all

SET _read=
SPLITSTR.BAT

Code: Select all

@echo off
rem Splits a string into parts by the standard delimiters
rem The input string has to be stored in "str"
rem @returnvar Name of the variable array to return 

rem Usage: call SPLTSTR.BAT result
rem Example for: str=Hello world, how are you
REM Output: 
REM result[0]=Hello
REM result[1]=world
REM result[2]=how
REM result[3]=are
REM result[4]=you

for %%L in (/%0) do if "%%L"=="/" goto %1

:main
set _idx=0
set _varname=%1
FOR %%W in (%str%) DO CALL %0// :store %%W

:clear
REM Clear temp vars
FOR %%v in (_idx _varname) do set %%v=
goto :eof

:store
set %_varname%[%_idx%]=%2
call INC.BAT %_idx% _idx
:eof

cajunjon
Posts: 2
Joined: 01 Apr 2021 09:10

Re: MS-DOS 6.22 variable trimming

#3 Post by cajunjon » 09 Apr 2021 12:43

Jeb,
Wow. I see why your title is expert! Thanks for the help. I'm offsite for a few weeks so I'll have to make the changes when I get back.
-Cajunjon

jeb
Expert
Posts: 980
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: MS-DOS 6.22 variable trimming

#4 Post by jeb » 12 Apr 2021 09:17

After review your original problem, I see it's considerably easier, because the output of your program can be used directly.
I assume, the output always begins with "CPU_0"
You only need two files (GETCPUID.bat and ADD.BAT)

GETCPUID.bat

Code: Select all

@echo off
REM Trampoline function
for %%L in (%0) do if "%%L"=="/" goto %1

> CPU_0.BAT echo %0// :value_fetched %%4

rdmsr.exe 0x198 > $CPU_TMP.BAT

call $CPU_TMP.BAT
del $CPU_TMP.BAT
del CPU_0.BAT
goto :eof

:value_fetched
set _remain=%2
echo part=%_remain%
call %0// :substr
call %0// :toHex _value1 %_chr1%
call %0// :toHex _value2 %_chr2%

call ADD.bat %_value1_16% %_value2% _cpu_value
echo CPU-ID 0x%_chr1%%_chr2%=%_cpu_value%

REM Clear variables
for %%V in (_chr1 _chr2 _cnt _value1 _value1_16 _value2 _value2_16 _cpu_value) do set %%V=
goto :eof

:substr
REM Get the 3 and 4 char
set _chr1=
set _chr2=
set _cnt=

:split_loop
set _loop=1

for %%a in (/%_remain%) do call %0// :split %%a
if NOT "%_remain%"=="" goto :split_loop

goto :eof

:split
set _remain=%2
if "%_loop%"=="" goto :eof
set _loop=
set _remain=
set _cnt=%_cnt%#
if %_cnt%==### set _chr1=%2
if %_cnt%==#### set _chr2=%2
goto :eof

:toHex
set %2=%3
goto :_toHex_%3
:_toHex_0
set %2_16=0
goto :eof
:_toHex_1
set %2_16=16
goto :eof
:_toHex_2
set %2_16=32
goto :eof
:_toHex_3
set %2_16=48
goto :eof
:_toHex_4
set %2_16=64
goto :eof
:_toHex_5
set %2_16=80
goto :eof
:_toHex_6
set %2_16=96
goto :eof
:_toHex_7
set %2_16=112
goto :eof
:_toHex_8
set %2_16=128
goto :eof
:_toHex_9
set %2_16=144
goto :eof
:_toHex_A
set %2=10
set %2_16=160
goto :eof
:_toHex_B
set %2=11
set %2_16=176
goto :eof
:_toHex_C
set %2=12
set %2_16=192
goto :eof
:_toHex_D
set %2=13
set %2_16=208
goto :eof
:_toHex_E
set %2=14
set %2_16=224
goto :eof
:_toHex_F
set %2=15
set %2_16=240
goto :eof

:eof

ADD.BAT

Code: Select all

@echo off
REM Trampoline function
for %%L in (%0) do if "%%L"=="/" goto %1

call %0// :split _valueRev1 %1
call %0// :split _valueRev2 %2

set _result=
set _carry=
for %%d in (%_valueRev1_comma%,0,0,0,0,0) do call %0// :getDig1 %%d


REM Remove leading zeros
:zeroLoop
for %%z in (/%_result%) do set _remain=%%z
if not %_result%==0%_remain% goto :finish
set _result=%_remain%
goto :zeroLoop

:finish
if "%3"=="" echo %1+%2=%_result%
if NOT "%3"=="" set %3=%_result%

REM Clear temp vars
FOR %%v in (_result _carry _len _digit1 _digit2 _remain) do set %%v=
FOR %%v in (_cnt _val _valueRev1 _valueRev1_comma _valueRev2 _valueRev2_comma) do set %%v=
goto :eof

:split
set _remain=%3
set _splitRev=
set _splitRev_comma=

:split_loop
set _loop=1
for %%a in (/%_remain%) do call %0// :split_char %%a
if NOT "%_remain%"=="" goto :split_loop
set %2=%_splitRev%
set %2_comma=%_splitRev_comma%
REM Clear temp vars
FOR %%v in (_remain _loop _splitRev _splitRev_comma) do set %%v=
goto :eof

:split_char
set _remain=%2
if "%_loop%"=="" goto :eof
set _loop=
set _remain=
set _splitRev=%2%_splitRev%
set _splitRev_comma=%2,%_splitRev_comma%
goto :eof

:getDig1
set _digit1=%2
set _digit2=
for %%d in (/%_valueRev2%0) do call %0// :getDig2 %%d

set _len=%_carry%
call %0// :lenAddDigit %_digit1%
call %0// :lenAddDigit %_digit2%
call %0// :len2val
set _result=%_val%%_result%
goto :eof

:getDig2
if not "%_digit2%"==" set _valueRev2=%2
if "%_digit2%"=="" set _digit2=%2
goto :eof

:lenAddDigit
if %2==1 set _len=%_len%#
if %2==2 set _len=%_len%##
if %2==3 set _len=%_len%###
if %2==4 set _len=%_len%####
if %2==5 set _len=%_len%#####
if %2==6 set _len=%_len%######
if %2==7 set _len=%_len%#######
if %2==8 set _len=%_len%########
if %2==9 set _len=%_len%#########
goto :eof

:len2val
set _carry=
set _val=
if %_len%.==. set _val=0
if %_len%.==. goto :eof
if %_len%==# set _val=1
if %_len%==## set _val=2
if %_len%==### set _val=3
if %_len%==#### set _val=4
if %_len%==##### set _val=5
if %_len%==###### set _val=6
if %_len%==####### set _val=7
if %_len%==######## set _val=8
if %_len%==######### set _val=9
if NOT "%_val%"=="" goto :eof
set _carry=#

if %_len%==########## set _val=0
if %_len%==########### set _val=1
if %_len%==############ set _val=2
if %_len%==############# set _val=3
if %_len%==############## set _val=4
if %_len%==############### set _val=5
if %_len%==################ set _val=6
if %_len%==################# set _val=7
if %_len%==################## set _val=8
if %_len%==################### set _val=9
goto :eof

:eof

Post Reply