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.
MS-DOS 6.22 variable trimming
Moderator: DosItHelp
Re: MS-DOS 6.22 variable trimming
Hi cajunjon,
you could split your problem into smaller problems and use some helper files.
The list of your problems
call READ.BAT 198.txt line
Problem 2 can be solved with SUBSTR.BAT (requires INC.BAT)
Problem 3 can be solved, if you take only the 5th word of your string by using a simple FOR loop, see SPLITSTR.BAT
Only problem4 isn't solved yet, but the solution should be obvious
SUBSTR.BAT
INC.BAT
READ.BAT
READ.HLP
SPLITSTR.BAT
you could split your problem into smaller problems and use some helper files.
The list of your problems
- You need to assign the program output to a variable
- Split a string into parts
- substring works only for strings without spaces or other delimiters
- A variable can't contain an equal sign (or I don't know how to assign it)
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
Code: Select all
call READ.BAT 198.txt str
call SPLITSTR strparts
set str=%strparts[4]%
call SUBSTR.BAT 2 2 result
echo %result%
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
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
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=
Code: Select all
SET _read=
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
Re: MS-DOS 6.22 variable trimming
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
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
Re: MS-DOS 6.22 variable trimming
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
ADD.BAT
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
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